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:
It filters out the lines that don't match while I want to include them in the output.
It doesn't highlight all the matching strings; it seems like the order in which the
-e
expressions are provided matters edit (noticed with BSDgrep
).
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