I find grep
's --color=always
flag to be tremendously useful. However, grep only prints lines with matches (unless you ask for context lines). Given that each line it prints has a match, the highlighting doesn't add as much capability as it could.
I'd really like to cat
a file and see the entire file with the pattern matches highlighted.
Is there some way I can tell grep to print every line being read regardless of whether there's a match? I know I could write a script to run grep on every line of a file, but I was curious whether this was possible with standard grep
.
sed
. the sed
solution gets you multiple colors at the cost of added complexity (instead of about 30 characters you have about 60 characters).
sed
you could event send a beep on console terminal: stackoverflow.com/a/69266748/1765658
Here are some ways to do it:
grep --color 'pattern\|$' file
grep --color -E 'pattern|$' file
egrep --color 'pattern|$' file
The |
symbol is the OR operator. Either escape it using \
or tell grep that the search text has to be interpreted as regular expressions by adding -E or using the egrep
command instead of grep
.
The search text "pattern|$" is actually a trick, it will match lines that have pattern
OR lines that have an end. Because all lines have an end, all lines are matched, but the end of a line isn't actually any characters, so it won't be colored.
To also pass the colored parts through pipes, e.g. towards less
, provide the always
parameter to --color
:
grep --color=always 'pattern\|$' file | less -r
grep --color=always -E 'pattern|$' file | less -r
egrep --color=always 'pattern|$' file | less -r
Here's something along the same lines. Chances are, you'll be using less anyway, so try this:
less -p pattern file
It will highlight the pattern and jump to the first occurrence of it in the file.
You can jump to the next occurence with n
and to the previous occurence with p
. Quit with q
.
-
: … | less -p pattern -
-i
option will make the match case insensitive as in less -ip pattern file
.
less
with the -R
switch: … | less -Rip introduction -
I'd like to recommend ack -- better than grep, a power search tool for programmers.
$ ack --color --passthru --pager="${PAGER:-less -R}" pattern files
$ ack --color --passthru pattern files | less -R
$ export ACK_PAGER_COLOR="${PAGER:-less -R}" $ ack --passthru pattern files
I love it because it defaults to recursive searching of directories (and does so much smarter than grep -r
), supports full Perl regular expressions (rather than the POSIXish regex(3)
), and has a much nicer context display when searching many files.
ack
is smart, but sometimes too smart, and it exluded the file type that the hit was in.
ack -a
will search all file types, while still excluding .git/
.svn/
etc.
ack
does not search through my images, so -a
does too much. I added --type-set=freemarker=.ftl
to my ~/.ackrc
, to give one example.
You can use my highlight
script from https://github.com/kepkin/dev-shell-essentials
It's better than grep
because you can highlight each match with its own color.
$ command_here | highlight green "input" | highlight red "output"
https://i.stack.imgur.com/XbB4X.png
grep
, which is a standard utility on machines running *nix.
colout
mentioned in another answer.
colout
, which is good if you want to inspect what it does.
You can also create an alias. Add this function in your .bashrc (or .bash_profile on osx)
function grepe {
grep --color -E "$1|$" $2
}
You can now use the alias like this: "ifconfig | grepe inet
" or "grepe css index.html
".
(PS: don't forget to source ~/.bashrc
to reload bashrc on current session)
--color=always
instead of --color
less
interpret the color codes, use less -R
.
Use colout
program: http://nojhan.github.io/colout/
It is designed to add color highlights to a text stream. Given a regex and a color (e.g. "red"), it reproduces a text stream with matches highlighted. e.g:
# cat logfile but highlight instances of 'ERROR' in red
colout ERROR red <logfile
You can chain multiple invocations to add multiple different color highlights:
tail -f /var/log/nginx/access.log | \
colout ' 5\d\d ' red | \
colout ' 4\d\d ' yellow | \
colout ' 3\d\d ' cyan | \
colout ' 2\d\d ' green
Or you can achieve the same thing by using a regex with N groups (parenthesised parts of the regex), followed by a comma separated list of N colors.
vagrant status | \
colout \
'\''(^.+ running)|(^.+suspended)|(^.+not running)'\'' \
green,yellow,red
grep
, and it is already expanded in the answers, colout
is the best solution for the problem you had, the best that I'm aware of. According to UNIX philosophy, programs should be written to do one thing well. For grep
it is filtering text stream. For colout
it is colorizing or highlighting text stream.
colout
is such a widely-useful tool. Learn it once, use it in many situations, rather than learning one tool to highlight logfiles, another to highlight test output, etc.
The -z
option for grep is also pretty slick!
cat file1 | grep -z "pattern"
echo "hello\nthere" | grep -z x
.
I use rcg from "Linux Server Hacks", O'Reilly. It's perfect for what you want and can highlight multiple expressions each with different colours.
#!/usr/bin/perl -w
#
# regexp coloured glasses - from Linux Server Hacks from O'Reilly
#
# eg .rcg "fatal" "BOLD . YELLOW . ON_WHITE" /var/adm/messages
#
use strict;
use Term::ANSIColor qw(:constants);
my %target = ( );
while (my $arg = shift) {
my $clr = shift;
if (($arg =~ /^-/) | !$clr) {
print "Usage: rcg [regex] [color] [regex] [color] ...\n";
exit(2);
}
#
# Ugly, lazy, pathetic hack here. [Unquote]
#
$target{$arg} = eval($clr);
}
my $rst = RESET;
while(<>) {
foreach my $x (keys(%target)) {
s/($x)/$target{$x}$1$rst/g;
}
print
}
I added this to my .bash_aliases:
highlight() {
grep --color -E "$1|\$"
}
As grep -E '|pattern'
has already been suggested, just wanted to clarify that it's possible to highlight a whole line too.
For example, tail -f somelog | grep --color -E '| \[2\].*'
(specifically, the part -E '|
):
https://i.imgur.com/HmfeYOR.png
The sed way
As there is already a lot of different solution, but none show sed
as solution,
and because sed
is lighter and quicker than grep
, I prefer to use sed
for this kind of job:
sed 's/pattern/\o33[47;31;1m&\e[0m/' file
This seem less intuitive.
\o33 is the sed syntax to generate character octal 033 -> Escape.
Esc [ 47 ; 31 ; 1 m are ANSI escape code: Background grey, foreground red and bold face.
& will re-print the pattern
Esc [ 0 m return to default.
By using this, you could higlight entire line, but marking pattern is red:
sed <file -e \
's/^\(.*\)\(234\)\(.*\)/\o33[47m\1\o33[31;1m\2\o33[0;47m\3\o33[0m/'
Dynamic tail -f, following logfiles
One of advantage of using sed
: You could send a alarm beep on console, using bell ascii character 0x7
. I often use sed like:
sudo tail -f /var/log/kern.log |
sed -ue 's/[lL]ink .*\([uU]p\|[dD]own\)/\o33[47;31;1m&\o33[0m\o7/'
-u stand for unbuffered. So line will be treated immediately.
So I will hear some beep when I connect or disconnect ethernet cable.
Of course, instead of link up
pattern, you could watch for USB
in same file, or even search for from=
in some /var/log/mail.log
...
Here is a shell script that uses Awk's gsub function to replace the text you're searching for with the proper escape sequence to display it in bright red:
#! /bin/bash
awk -vstr=$1 'BEGIN{repltext=sprintf("%c[1;31;40m&%c[0m", 0x1B,0x1B);}{gsub(str,repltext); print}' $2
Use it like so:
$ ./cgrep pattern [file]
Unfortunately, it doesn't have all the functionality of grep.
For more information , you can refer to an article "So You Like Color" in Linux Journal
One other answer mentioned grep's -Cn switch which includes n lines of Context. I sometimes do this with n=99 as a quick-and-dirty way of getting [at least] a screenfull of context when the egrep pattern seems too fiddly, or when I'm on a machine on which I've not installed rcg and/or ccze.
I recently discovered ccze
which is a more powerful colorizer. My only complaint is that it is screen-oriented (like less
, which I never use for that reason) unless you specify the -A switch for "raw ANSI" output.
+1 for the rcg
mention above. It is still my favorite since it is so simple to customize in an alias. Something like this is usually in my ~/.bashrc:
alias tailc='tail -f /my/app/log/file | rcg send "BOLD GREEN" receive "CYAN" error "RED"'
another dirty way:
grep -A80 -B80 --color FIND_THIS IN_FILE
I did an
alias grepa='grep -A80 -B80 --color'
in bashrc.
I use following command for similar purpose:
grep -C 100 searchtext file
This will say grep to print 100 * 2 lines of context, before & after of the highlighted search text.
It might seem like a dirty hack.
grep "^\|highlight1\|highlight2\|highlight3" filename
Which means - match the beginning of the line(^) or highlight1 or highlight2 or highlight3. As a result, you will get highlighted all highlight* pattern matches, even in the same line.
Use ripgrep, aka rg: https://github.com/BurntSushi/ripgrep
rg --passthru...
Color is the default:
https://i.stack.imgur.com/XuUHy.png
rg -t tf -e 'key.*tfstate' -e dynamodb_table
--passthru
Print both matching and non-matching lines.
Another way to achieve a similar effect is by modifying your pattern to
match the empty string.
For example, if you are searching using rg foo then using
rg "^|foo" instead will emit every line in every file searched, but only
occurrences of foo will be highlighted.
This flag enables the same behavior without needing to modify the pattern.
Sacrilege, granted, but grep has gotten complacent.
brew/apt/rpm/whatever install ripgrep
You'll never go back.
rg --passthru 'setuptools' <(poetry show --tree)
grep
, may I introduce to you ugrep
, which beats ripgrep
in performance — and basically everything else out there — while, at the same time, adding lots of extra goodies. In my case, since ugrep
includes the --replace
option, I've since given up on sed
and its quirky handling of regexps... and, unlike standard grep
, ugrep
is much faster than sed
.
Ok, this is one way,
wc -l filename
will give you the line count -- say NN, then you can do
grep -C NN --color=always filename
echo "hello\nthere" | grep -C99 x
produces nothing.
If you want highlight several patterns with different colors see this bash script.
Basic usage:
echo warn error debug info 10 nil | colog
You can change patterns and colors while running pressing one key and then enter key.
Here's my approach, inspired by @kepkin's solution:
# Adds ANSI colors to matched terms, similar to grep --color but without
# filtering unmatched lines. Example:
# noisy_command | highlight ERROR INFO
#
# Each argument is passed into sed as a matching pattern and matches are
# colored. Multiple arguments will use separate colors.
#
# Inspired by https://stackoverflow.com/a/25357856
highlight() {
# color cycles from 0-5, (shifted 31-36), i.e. r,g,y,b,m,c
local color=0 patterns=()
for term in "$@"; do
patterns+=("$(printf 's|%s|\e[%sm\\0\e[0m|g' "${term//|/\\|}" "$(( color+31 ))")")
color=$(( (color+1) % 6 ))
done
sed -f <(printf '%s\n' "${patterns[@]}")
}
This accepts multiple arguments (but doesn't let you customize the colors). Example:
$ noisy_command | highlight ERROR WARN
Is there some way I can tell grep to print every line being read regardless of whether there's a match?
Option -C999
will do the trick in the absence of an option to display all context lines. Most other grep variants support this too. However: 1) no output is produced when no match is found and 2) this option has a negative impact on grep's efficiency: when the -C
value is large this many lines may have to be temporarily stored in memory for grep to determine which lines of context to display when a match occurs. Note that grep implementations do not load input files but rather reads a few lines or use a sliding window over the input. The "before part" of the context has to be kept in a window (memory) to output the "before" context lines later when a match is found.
A pattern such as ^|PATTERN
or PATTERN|$
or any empty-matching sub-pattern for that matter such as [^ -~]?|PATTERN
is a nice trick. However, 1) these patterns don't show non-matching lines highlighted as context and 2) this can't be used in combination with some other grep options, such as -F
and -w
for example.
So none of these approaches are satisfying to me. I'm using ugrep, and enhanced grep with option -y
to efficiently display all non-matching output as color-highlighted context lines. Other grep-like tools such as ag and ripgrep also offer a pass-through option. But ugrep is compatible with GNU/BSD grep and offers a superset of grep options like -y
and -Q
. For example, here is what option -y
shows when combined with -Q
(interactive query UI to enter patterns):
ugrep -Q -y FILE ...
Also try:
egrep 'pattern1|pattern2' FILE.txt | less -Sp 'pattern1|pattern2'
This will give you a tabular output with highlighted pattern/s.
Success story sharing
egrep --color "pattern|" file
(credit stackoverflow.com/a/7398092/50979)egrep --color "pattern1|pattern2|$"
. Otherwise the color highlighting does not happen.