ansi styles
Wednesday, 14 October 2026 11:10 pmFor a long time it has bugged me that there is no easy way to add ANSI codes to a text file or the output of a command. I would have to add them in a tedious way with sed or awk and try to remember the obscure escape codes for the ANSI sequences. Well, I've written a surprisingly simple bash script that lets me pipe any text or output of any command through it and do things like:
anstyle line 4 bold
or
anstyle str elephant red g
The first one makes the fourth line of whatever is piped into it bold text. (Surprise, surprise.) The second one prints in red every occurrence of "elephant" in the piped text.
But you can do more complex things too, like reversing the foreground and background colors of all lines between and including two line numbers. You can change to italic all lines between and including two lines that contain a start string and a stop string. You can highlight the last line of the input file (regardless of how long the file is) by making its background some color, say, yellow. And much more.
And I can include several of those definitions in the single anstyle command. I'm very happy that this makes a lot of minor, but annoying things into trivial tasks.
anstyle line 4 bold
or
anstyle str elephant red g
The first one makes the fourth line of whatever is piped into it bold text. (Surprise, surprise.) The second one prints in red every occurrence of "elephant" in the piped text.
But you can do more complex things too, like reversing the foreground and background colors of all lines between and including two line numbers. You can change to italic all lines between and including two lines that contain a start string and a stop string. You can highlight the last line of the input file (regardless of how long the file is) by making its background some color, say, yellow. And much more.
And I can include several of those definitions in the single anstyle command. I'm very happy that this makes a lot of minor, but annoying things into trivial tasks.
#! /bin/bash
# anstyle
# ANSI styling of text via simple commands
# Miriam
# Saturday 2026-10-10 09:49:30 pm
#
# This grew out of my frustration that I couldn't do easy ANSI styling
# of a command's output without resorting to fairly obscure uses
# of awk or sed for what may be a quick, off-hand, one-time use.
#
# line
# awk 'NR==1 {print "\033[1m" $0 "\033[0m";next}1'
# awk 'NR==1 {print "\033[1m" $0 "\033[0m"} NR>1'
# range
# awk 'NR==4, NR==6{print "\033[1m" $0 "\033[0m";next}1'
# awk '/dev/,/tmp/{print "\033[1m" $0 "\033[0m";next}1'
# awk 'NR==4, 0{print "\033[1m" $0 "\033[0m";next}1'
# awk 'NR>=4{print "\033[1m" $0 "\033[0m";next}1'
# string highlight
# awk '{gsub(/dev/, "\033[31mdev\033[0m"); print}'
# In order to select the nth match awk needs a loop and counter
#
# line
# sed '1s/^/\c[[1m/; 1s/$/\c[[0m/'
# sed '1s/.*/\c[[1m&\c[[0m/'
# line range
# sed '2,$s/.*/\c[[1m&\c[[0m/'
# sed '/nvme/,/user/s/.*/\c[[31m&\c[[0m/'
# string highlight
# sed 's/dev/\c[[31m&\c[[0m/g' # all occurrences of "dev"
# sed 's/dev/\c[[31m&\c[[0m/2' # 2nd occurrence on every line
# sed -z 's/dev/\c[[31m&\c[[0m/4' # 4th occurrence in the file
# multiple commands
# sed '1s/.*/\c[[1m&\c[[0m/;/nvme/,/user/s/.*/\c[[31m&\c[[0m/'
#
# NOTE: ASCII escape char is \d27 or \o033 or \x1b or \c[
#
# Commands
# line affects the nth line
# line affects lines containing pattern
# line affects given lines
# str
# Perhaps use commands like this:
# anstyle line 1,3 bold line 5 redfg str text italic 2 file.txt
# makes file.txt lines 1 to 3 bold, line 5 red fg, 2nd pattern "text" italic
declare -A ansi
ansi[reset]='\c[[0m'
ansi[bold]='\c[[1m'
ansi[unbold]='\c[[21m'
ansi[dim]='\c[[2m'
ansi[undim]='\c[[22m'
ansi[italic]='\c[[3m'
ansi[unitalic]='\c[[23m'
ansi[uline]='\c[[4m'
ansi[unuline]='\c[[24m'
ansi[blink]='\c[[5m'
ansi[unblink]='\c[[25m'
ansi[fblink]='\c[[6m'
ansi[unfblink]='\c[[26m'
ansi[reverse]='\c[[7m'
ansi[unreverse]='\c[[27m'
ansi[hide]='\c[[8m'
ansi[unhide]='\c[[28m'
ansi[strike]='\c[[9m'
ansi[unstrike]='\c[[29m'
# ===colors ===
# --- fg ---
ansi[black]='\c[[30m'
ansi[red]='\c[[31m'
ansi[green]='\c[[32m'
ansi[orange]='\c[[33m'
ansi[blue]='\c[[34m'
ansi[violet]='\c[[35m'
ansi[cyan]='\c[[36m'
ansi[lgray]='\c[[37m'
# --- bg ---
ansi[blackbg]='\c[[40m'
ansi[redbg]='\c[[41m'
ansi[greenbg]='\c[[42m'
ansi[orangebg]='\c[[43m'
ansi[bluebg]='\c[[44m'
ansi[violetbg]='\c[[45m'
ansi[cyanbg]='\c[[46m'
ansi[lgraybg]='\c[[47m'
# --- light colors ---
# --- fg ---
ansi[dgray]='\c[[30m'
ansi[lred]='\c[[31m'
ansi[lgreen]='\c[[32m'
ansi[yellow]='\c[[33m'
ansi[lblue]='\c[[34m'
ansi[lviolet]='\c[[35m'
ansi[lcyan]='\c[[36m'
ansi[white]='\c[[37m'
# --- bg ---
ansi[dgraybg]='\c[[40m'
ansi[lredbg]='\c[[41m'
ansi[lgreenbg]='\c[[42m'
ansi[yellowbg]='\c[[43m'
ansi[lbluebg]='\c[[44m'
ansi[lvioletbg]='\c[[45m'
ansi[lcyanbg]='\c[[46m'
ansi[whitebg]='\c[[47m'
file=""
line=""
str=""
ansi=""
# Create a temp file and ensure it's cleaned up on exit
TMPFILE=$(mktemp)
trap 'rm -f "$TMPFILE"' EXIT
cat > "$TMPFILE"
# collect all options and arguments
while [[ "$#" -gt 0 ]]; do
case "$1" in
line)
shift
line=$1
shift
style=$1
shift
sed -i ${line}'s/.*/'${ansi[$style]}'&'${ansi[reset]}/ "$TMPFILE"
;;
str)
shift
str=$1
shift
style=$1
shift
n=$1
shift
sed -i -z 's/'$str'/'${ansi[$style]}'&'${ansi[reset]}'/'$n "$TMPFILE"
;;
*)
# not used at the moment a file can only be piped in
#file=$1
#shift
blah="$@"
echo -e "\033[31mError! Unknown text at the end of commandline: ${blah}\033[0m"
exit
;;
esac
done
cat "$TMPFILE"





