Skip to content

Instantly share code, notes, and snippets.

@nachoparker
Last active December 28, 2017 16:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save nachoparker/e6cc69c6cb3b1c8fe581c49eefaba788 to your computer and use it in GitHub Desktop.
Save nachoparker/e6cc69c6cb3b1c8fe581c49eefaba788 to your computer and use it in GitHub Desktop.
colorize your stdout with xcol for bash
#!/bin/bash
# Simple colorize for bash by means of sed
#
# Copyright 2008-2015 by Andreas Schamanek <andreas@schamanek.net>
#
# 2017 - Modified from mycolorize into a shell function
# by Ignacio Nunez Hernanz <nacho _a_t_ ownyourbits _d_o_t_ com>
#
# GPL licensed (see end of file) * Use at your own risk!
#
# Usage examples:
# tail -f somemaillog | xcolorize white '^From: .*' bell
# tail -f somemaillog | xcolorize white '^From: \/.*' green 'Folder: .*'
# tail -f somemaillog | xcolorize --unbuffered white '^From: .*'
#
# Notes:
# Regular expressions need to be suitable for _sed --regexp-extended_
# Slashes / need no escaping (we use ^A as delimiter).
# \/ splits the coloring (similar to procmailrc. Matches behind get color.
# Even "white '(for|to) \/(her|him).*$'" works :) Surprisingly ;)
# To color the string '\/' use the regular expression '\\()/'.
# If the 1st argument is -u or --unbuffered, _sed_ will be run so.
# For the colors see tput(1) and terminfo(5), or e.g.
# https://wiki.archlinux.org/index.php/Color_Bash_Prompt
# and http://stackoverflow.com/a/20983251/196133
function xcolorize()
{
local bold=$(tput bold) # make colors bold/bright
local normal=$'\e[0m' # (works better sometimes)
local red="$bold$(tput setaf 1)" # bright red text
local green=$(tput setaf 2) # dim green text
local fawn=$(tput setaf 3); beige="$fawn" # dark yellow text
local yellow="$bold$fawn" # bright yellow text
local darkblue=$(tput setaf 4) # dim blue text
local blue="$bold$darkblue" # bright blue text
local purple=$(tput setaf 5); magenta="$purple" # magenta text
local pink="$bold$purple" # bright magenta text
local darkcyan=$(tput setaf 6) # dim cyan text
local cyan="$bold$darkcyan" # bright cyan text
local gray=$(tput setaf 7) # dim white text
local darkgray="$bold"$(tput setaf 0) # bold black = dark gray text
local white="$bold$gray" # bright white text
local bell=$(tput bel) # bell/beep
local y=0
# Make output unbuffered? (Pass argument -u|--unbuffered to _sed_.)
if [ "/$1/" = '/-u/' -o "/$1/" = '/--unbuffered/' ] ; then
local UNBUFFERED='-u'; shift
else
local UNBUFFERED=""
fi
# produce separator character ^A (for _sed_)
local A=$(echo | tr '\012' '\001')
# compile all rules given at command line to 1 set of rules for SED
while [ "/$1/" != '//' ] ; do
local c1=''; local re=''; local beep=''
c1=$1 ; re="$2" ; shift 2 || break
# if a beep is requested in the optional 3rd parameter set $beep
[ "/$1/" != '//' ] && [[ ( "$1" = 'bell' || "$1" = 'beep' ) ]] \
&& beep=$bell && shift
# if the regular expression includes \/ we split the substitution
if [ "/${re/*\\\/*/}/" = '//' ] ; then
# we need to count "("s before the \/ (=$left)
local left="${re%\\/*}"; local leftlength=${#left}
# first we count "\("
local dummy=${left//\\(}; escdgroups=$(( (leftlength-${#dummy})/2 ))
# now "(" (and we add 2 for the groups used for ($re) in $sedrules)
local dummy=${left//(}; groupcnt=$((leftlength-${#dummy}-escdgroups+2))
# replace \/ with )( so below we get (left-re)(right-re)
re="${re/\\\//)(}"
local sedrules="$sedrules;s$A($re)$A\1${!c1}\\$groupcnt$beep$normal${A}g"
sedrules="${sedrules}I" # add case insensitive
else
local sedrules="$sedrules;s$A($re)$A${!c1}\1$beep$normal${A}g"
sedrules="${sedrules}I" # add case insensitive
fi
# limit parsing of arguments
(( y++ && y>888 )) && { echo "$0: too many arguments" >&2; return 1; }
done
# call sed to do the main job
sed $UNBUFFERED --regexp-extended -e "$sedrules"
return
}
# Colorize your standard output using xcolorize with a grep-like usage
#
# Copyleft 2017 by Ignacio Nunez Hernanz <nacho _a_t_ ownyourbits _d_o_t_ com>
# GPL licensed (see end of file) * Use at your own risk!
#
# Usage piping from stdin:
# mount | xcol mnt "sda." "sdb." cgroup tmpfs proc
#
# Usage reading from a file:
# xcol pae fpu vme mhz sse2 cache cores /proc/cpuinfo
#
# Notes:
# It supports sed compatible regular expressions
function xcol()
{
local bold=$(tput bold) # make colors bold/bright
local red="$bold$(tput setaf 1)" # bright red text
local green=$(tput setaf 2) # dim green text
local fawn=$(tput setaf 3); beige="$fawn" # dark yellow text
local yellow="$bold$fawn" # bright yellow text
local darkblue=$(tput setaf 4) # dim blue text
local blue="$bold$darkblue" # bright blue text
local purple=$(tput setaf 5); magenta="$purple" # magenta text
local pink="$bold$purple" # bright magenta text
local darkcyan=$(tput setaf 6) # dim cyan text
local cyan="$bold$darkcyan" # bright cyan text
local gray=$(tput setaf 7) # dim white text
local darkgray="$bold"$(tput setaf 0) # bold black = dark gray text
local white="$bold$gray" # bright white text
local COLS=( white yellow red cyan gray purple pink fawn )
[ -t 0 ] && local STDIN=0 || local STDIN=1
if [[ $STDIN == 0 ]]; then
local ARGVS=${@: 1 : $#-1 } # all arguments except last one
local FILE=${@: -1} # last argument is the file name
else
local ARGVS=$@;
fi
local IDX=1 # rotate colors in a cycle
for arg in ${ARGVS[@]}; do
local ARGS=( ${ARGS[@]} ${COLS[$IDX]} $arg )
IDX=$(( IDX + 1 ))
[[ $IDX == ${#COLS[@]} ]] && IDX=1
done
[[ $STDIN == 1 ]] && {
xcolorize --unbuffered ${ARGS[@]}
} || {
cat $FILE | xcolorize --unbuffered ${ARGS[@]}
}
}
# License
#
# This script is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This script is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this script; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place, Suite 330,
# Boston, MA 02111-1307 USA
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment