ANSI Colors on console term
Preamble: about $TERM variable
Verify your environment with: tput colors
If you use some compatible xterm console, your $TERM may contain something like xterm*:
echo $TERM xterm tput colors 8 Further demos won't work: you will get image looking like:
unless you set this to xterm-256color:
export TERM=xterm-256color ; reset tput colors 256 ( You could even try to run this after setting export TERM=xterm-mono ;)
Doing simply the job by using tput
Depending on wich term protocol your console use, sequence could be: \e[38;5;XXXm or \e[3XXXm where XXX correspond to ansi number.
To ensure you use the right ANSI sequence, you have to use tput.
Regarding to Wikipedia's ANSI escape code, I wrote this:
#!/bin/bash for ((i=0; i<256; i++)) ;do echo -n ' ' tput setab $i tput setaf $(( ( ( i > 231 && i < 244 ) || ( ( i < 17 ) && ( i % 8 < 2 ) ) || ( i > 16 && i < 232 ) && ( ( i - 16 ) % 6 * 11 + ( i - 16 ) / 6 % 6 * 14 + ( i - 16 ) / 36 * 10 ) < 58 ) ? 7 : 16 )) printf " C %3d " $i tput op (( ((i<16||i>231) && ((i+1)%8==0)) || ((i>16&&i<232)&& ((i-15)%6==0)) )) && printf "\n" done Should render something like:
Optimizing bash: reducing forks by running tput as background process
... Then, because I hate runnig more than 200 forks in a little script, I wrote this:
#!/bin/bash # Connector fifos directory read TMPDIR < <(mktemp -d /dev/shm/conn_shell_XXXXXXX) fd=3 # find next free fd nextFd() { while [ -e /dev/fd/$fd ];do ((fd++)) ;done;printf -v $1 %d $fd;} tputConnector() { mkfifo $TMPDIR/tput nextFd TPUTIN eval "exec $TPUTIN> >(LANG=C exec stdbuf -o0 tput -S - >$TMPDIR/tput 2>&1)" nextFd TPUTOUT eval "exec $TPUTOUT<$TMPDIR/tput" rm $TMPDIR/tput rmdir $TMPDIR } myTput() { echo -e "$1\ncr" 1>&$TPUTIN && IFS= read -r -d $'\r' -u $TPUTOUT $2 } tputConnector myTput op op myTput "setaf 7" grey myTput "setaf 16" black fore=("$black" "$grey") for ((i=0; i<256; i++)) ;do myTput "setab $i" bgr printf " %s%s %3d %s" "$bgr" "${fore[ i>231 && i<244||(i<17)&& (i%8<2)|| (i>16&&i<232)&&((i-16)%6*11+(i-16)/6%6*14+(i-16)/36*10)<58 ? 1 : 0 ]}" $i "$op" (( ((i<16||i>231) && ((i+1)%8==0)) || ((i>16&&i<232)&& ((i-15)%6==0)) )) && printf "\n" '' done With only 1 fork! Same result, but approx 10x faster!
If first script run in ~1.12 second on my desk, they take upto ~47.4 seconds on my raspberry-pi!!
While second script run in ~0.11 second on my desk and ~4.97 seconds on my raspberry.
Without forks, using ansi sequences
From 8-bit color chapter of Wikipedia's ANSI escape code, and to be quicker, without any loop:
#!/bin/bash shape='XXXXXXXX' arry=(0 0 2{,,}{,,}{,,,} 0{,,}) eval arry=(${arry[@]/?/\${shape:&\}}) printf -v shape '%s\n' "${arry[@]//X/ \\e[48;5;%d;38;5;%%%%dm C %%3d \\e[0m}" declare -ai arry=({0..255}) printf -v shape "$shape" ${arry[@]} printf -v shape "$shape" ${arry[@]} eval "arry=(${arry[@]/*/\"(&>231\&\&&<244)||((&<17)\&\&(&%8<2))||(&>16\&\& &<232)\&\&((&-16)%6*11+(&-16)/6%6*14+(&-16)/36*10)<58?7:16\"})" printf "$shape" ${arry[@]} Note: this could by cut'n pasted into a fresh terminal window.
Same script with some comments:
#!/bin/bash # Building a shape of 41 lines with two first lines of 8 fields, followed # by 36 lines of 6 fields, then 3 lines of 8 fields. shape='XXXXXXXX' # an 8 X string arry=(0 0 2{,,}{,,}{,,,} 0{,,}) # 2(x8) + 36(x6) + 3(x8): 41 lines eval arry=(${arry[@]/?/\${shape:&\}}) # 'arry=(XXXXXXXX XXXXXXXX XXXXXX ...' printf -v shape '%s\n' "${arry[@]//X/ \\e[48;5;%d;38;5;%%%%dm C %%3d \\e[0m}" # %d will be ANSI color, then %%3d right aligned label, and %%%%d foreground declare -ai arry=({0..255}) # arry is now an array of 256 integers printf -v shape "$shape" ${arry[@]} # populate colors printf -v shape "$shape" ${arry[@]} # populate labels # Building array of 256 foreground colors eval "arry=(${arry[@]/*/\"(&>231\&\&&<244)||((&<17)\&\&(&%8<2))||(&>16\&\& &<232)\&\&((&-16)%6*11+(&-16)/6%6*14+(&-16)/36*10)<58?7:16\"})" printf "$shape" ${arry[@]} # print out finalised shape with foregrounds Note: as this don't refer to tput, environment variable TERM doesn't matter.

