Search code examples
shellgrepcommand

Colorize specific strings in a text


I would like to highlight a few strings while outputting a text file. For example the literals [2], quick and lazy in:

... => any number of lines with non-matching content
He’s quick but lazy.
...
• The future belongs to those who believe in the beauty of their dreams [2].
...
I’m lazy but quick (2 times faster); is there a difference when "lazy" comes before "quick"?
...

My intuitive approach would be to use grep for the colorization (in fact I'm not fixed on any specific tool):

grep -F -e '[2]' -e 'quick' -e 'lazy' --color file.txt

But it has two problems:

  1. It filters out the lines that don't match while I want to include them in the output.

  2. It doesn't highlight all the matching strings; it seems like the order in which the -e expressions are provided matters (problem noticed with macOS grep).

My expected output (with <...> standing for the colorization) would be:

... => any number of lines with non-matching content
He’s <quick> but <lazy>.
...
• The future belongs to those who believe in the beauty of their dreams <[2]>.
...
I’m <lazy> but <quick> (2 times faster); is there a difference when "<lazy>" comes before "<quick>"?
...

Solution

  • grep -n -F -e '[2]' -e 'quick' -e 'lazy' --color=always file.txt |
    awk -F':' '
        FILENAME==ARGV[1] { n=substr($1,9,length($1)-22); sub(/[^:]+:/,""); a[n]=$0; next }
        { print (FNR in a ? a[FNR] : $0) }
    ' - file.txt
    

    would use grep to find and highlight the strings, and then awk would print the grep output for those lines and the original lines from the input file otherwise.