Home > OS >  Colorize specific strings in a text
Colorize specific strings in a text

Time:01-16

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 edit (noticed with BSD 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>"?
...

CodePudding user response:

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.

CodePudding user response:

I found a way using grep -E instead of grep -F. As a side-effect, matching a literal string will require its ERE-escaping.

The method is to build a single regex composed of the | union of the search strings, plus an additional ^ anchor that will select the "non-matching" lines.

Hence, for highlighting the literals [2], quick and lazy in the sample text, you can use:

grep -E '\[2]|quick|lazy|^' --color file.txt

note: tested with GNU and BSD grep

  • Related