3
$cat contents.txt

cat-1.15

cat-1.15

cat-1.15
cat-1.18

The above output has blank lines

$cat contents.txt | grep cat results in the word cat being highlighted, but the resultant text is also merged, eliminating blank lines

cat-1.15
cat-1.15
cat-1.15
cat-1.18

How can I grep to highlight without grep affecting the text structure, so that the only difference is the grep term being highlighted ?

4 Answers4

5

With GNU grep this can be accomplished with the -z option.

-z, --null-data

Treat input and output data as sequences of lines, each terminated by a zero byte (the ASCII NUL character) instead of a newline. Like the -Z or --null option, this option can be used with commands like sort -z to process arbitrary file names.

Also this is a UUOC. You can specify an input file with grep.

$ grep --color cat contents.txt
cat-1.15
cat-1.15
cat-1.15
cat-1.18
$ grep --color -z cat contents.txt
cat-1.15

cat-1.15

cat-1.15
cat-1.18
jesse_b
  • 37,005
  • 2
    Note that this will try to read the whole file into memory. If it is big, a big chunk of memory will be used. –  Jan 25 '19 at 19:51
4

Another possible solution is to provide two patterns to grep: one will be the actual pattern or term to be searched for, and the second one will be an empty string.

$ grep --color -e 'cat' -e '' testfile.txt
cat-1.15

cat-1.15

cat-1.15 cat-1.18

The -e option is used for specify multiple patterns. From the manual:

-e PATTERN, --regexp=PATTERN

Use PATTERN as the pattern. This can be used to specify multiple search patterns, or to protect a pattern beginning with a hyphen (-). (-e is specified by POSIX.)

You can also combine those patterns as a single extended regular expression, if required:

$ grep --color -E 'cat|' testfile.txt
cat-1.15

cat-1.15

cat-1.15 cat-1.18

Also, you can simply add another pattern to the list if you need to highlight more than one keyword.

Haxiel
  • 8,361
1

A couple more possibilities with grep:

grep for 0 or more instances of cat:

grep --color '\(cat\)*' contents.txt

grep for cat or the empty string:

grep -E --color 'cat|' contents.txt

(The -E specifies extended regex syntax. egrep may be used instead of grep -E here.)


Alternatively you can use sed to do the colourization manually using ANSI escape codes:

red='\c[[1;31m'
default='\c[[0m'
sed "s/cat/${red}cat${default}/g" contents.txt

Here the red and default shell variables are conveniences only - their values could just as well be placed inline in the sed expression.

0

I tried with below command

sed -r "/cat/{N;s/^$/&=/}" filename


awk '{if(((length($1)>3)&& ($1 ~ /cat/))||($0~/^$/)){print $0}}' filename