9

I'm a bit new to bash scripting, and I'm wondering if there is a program or built-in command to pipe to that will print in a specified color? Or is there an echo argument to do so?

Like I could do:

echo Hi | commandhere -arguement blue

and it would print "Hi" in the color blue?

1
  • I which grc worked this way rather than as a prefix command. Feb 29, 2016 at 23:46

5 Answers 5

11

I don't know of any utility for colored printing itself, but you can do it easily with a shell function like this:

# colorize stdin according to parameter passed (GREEN, CYAN, BLUE, YELLOW)
colorize(){
    GREEN="\033[0;32m"
    CYAN="\033[0;36m"
    GRAY="\033[0;37m"
    BLUE="\033[0;34m"
    YELLOW="\033[0;33m"
    NORMAL="\033[m"
    color=\$${1:-NORMAL}
    # activate color passed as argument
    echo -ne "`eval echo ${color}`"
    # read stdin (pipe) and print from it:
    cat
    # Note: if instead of reading from the pipe, you wanted to print
    # the additional parameters of the function, you could do:
    # shift; echo $*
    # back to normal (no color)
    echo -ne "${NORMAL}"
}
echo hi | colorize GREEN

If you want to check other colors, take a look at this list. You can add support for any color from there, simply creating an additional variable at this function with the correct name and value.

4
  • So I just put this into the file "colorize", mark it as executable and put it into /etc/bin ?
    – TenorB
    May 10, 2012 at 23:15
  • You can just copy the function to your .bashrc.
    – elias
    May 10, 2012 at 23:17
  • 1
    If you really want to do an executable file though, you should copy everything from within the function (inside the brackets) and put in a file "colorize", mark it as executable and put it in some directory in your $PATH variable (/usr/local/bin is a good place)
    – elias
    May 10, 2012 at 23:19
  • If you are like me and just trying to learn more about bash scripting, here's another script that does a very similar thing. Interesting to compare these two scripts. I am making my own to combine them.
    – floer32
    Nov 4, 2012 at 23:12
4

I created this function that I use in bash scripts.

# Function to echo in specified color
echoincolor () {
    case $1 in
        "red") tput setaf 1;;
        "green") tput setaf 2;;
        "orange") tput setaf 3;;
        "blue") tput setaf 4;;
        "purple") tput setaf 5;;
        "cyan") tput setaf 6;;
        "gray" | "grey") tput setaf 7;;
        "white") tput setaf 8;;
    esac
    echo "$2";
    tput sgr0
}

Then I just call it like this echoincolor green "This text is in green!"

Alternatively, use printf

# Function to print in specified color
colorprintf () {
    case $1 in
        "red") tput setaf 1;;
        "green") tput setaf 2;;
        "orange") tput setaf 3;;
        "blue") tput setaf 4;;
        "purple") tput setaf 5;;
        "cyan") tput setaf 6;;
        "gray" | "grey") tput setaf 7;;
        "white") tput setaf 8;;
    esac
    printf "$2";
    tput sgr0
}

Then just call it like this colorprintf green "This text is in green!"

Note, echo provides a trailing new line while printf does not.

1

I use this old script, names hilite.pl, taken from the web, already with the "unknown author" line!

#!/usr/bin/perl -w
### Usage: hilite <ansi command> <target string>
### Purpose: Will read text from standard input and perform specified highlighting
### command before displaying text to standard output.
### License: GNU GPL
# unknown author 

$|=1; # don't buffer i/o
$command = "$ARGV[0]";
$target = "$ARGV[1]";
$color = "\e[" . $command . "m";
$end = "\e[0m";

while(<STDIN>) {
    s/($target)/$color$1$end/;
    print $_;
}

Then i can use it in pipes, to "hilite" log output or other things, using regexp/PCRE:

 echo 'hello color world!!' | hilite.pl 34 "[Hh]el[^ ]*" | hilite.pl 43 .orld | hilite.pl 32 "\scolor\s"

This will paint hello in blue, color in green and world in yellow background

You can see the color list with (you can expand the bash expression to {01..255} if you want):

for i in {01..10}  {30..49} {90..110}  ; do echo $i | hilite.pl $i $i ; done
1

There is a much more elegant answer than any of these:

sudo apt-get install grc

(which also installs grcat)

Now execute:

echo "[SEVERE] Service is down" | grcat ~/conf.username

Where conf.myusername contains:

regexp=SEVERE
colours=on_red
count=more

(for some reason I can't find the right regexp for "everything between quotes")

0

I came across this question/answers trying to do something similar as the OP. I found some other useful resources and came up with a log script based on those. Posting here in case it can help others.

Digging into the links helps understand some of the redirection which I won't try and explain because I'm just starting to understand it myself.

Usage will render the colorized output to the console, while stripping the color codes out of the text going to the log file. It will also include stderr in the logfile for any commands that don't work.

Edit: adding more usage at bottom to show how to log in different ways

#!/bin/bash
set -e
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"

. $DIR/dev.conf
. $DIR/colors.cfg

filename=$(basename ${BASH_SOURCE[0]})
# remove extension
# filename=`echo $filename | grep -oP '.*?(?=\.)'`
filename=`echo $filename | awk -F\. '{print $1}'`
log=$DIR/logs/$filename-$target

if [ -f $log ]; then
  cp $log "$log.bak"
fi

exec 3>&1 4>&2
trap 'exec 2>&4 1>&3' 0 1 2 3
exec 1>$log 2>&1


# log message
log(){
    local m="$@"
    echo -e "*** ${m} ***" >&3
    echo "=================================================================================" >&3
  local r="$@"
    echo "================================================================================="
    echo -e "*** $r ***" | sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[mGK]//g"
    echo "================================================================================="
}

echo "=================================================================================" >&3
log "${Cyan}The ${Yellow}${COMPOSE_PROJECT_NAME} ${filename} ${Cyan}script has been executed${NC}"
log $(ls) #log $(<command>)

log "${Green}Apply tag to image $source with version $version${NC}"
# log $(exec docker tag $source $target 3>&2) #prints error only to console
# log $(docker tag $source $target 2>&1) #prints error to both but doesn't exit on fail
log $(docker tag $source $target 2>&1) && exit $? #prints error to both AND exits on fail
# docker tag $source $target 2>&1 | tee $log # prints gibberish to log
echo $? # prints 0 because log function was successful
log "${Purple}Push $target to acr${NC}"


Here are the other links that helped:

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .