Switching the color is done through escape sequences embedded in the text. Invariably, programs issue ANSI escape sequences, because that's what virtually all terminals support nowadays.
The escape sequence to switch the foreground color to red is \e[31m
, where \e
designates an escape character (octal 033, hexadecimal 1b, also known as ESC, ^[
and various other designations). Numbers in the range 30–39 set the foreground color; other numbers set different attributes. \e[0m
resets all attributes to their default value. Run cat -v
to check what the program prints, it might use some variant such as \e[0;31m
to first reset all attributes, or \e[3;31
to also switch italics on (which many terminals don't support).
In ksh, bash or zsh, you can use $'…'
to enable backslash escapes inside the quotes, which lets you type $'\e'
to get an escape character. Note that you will then have to double any backslash that you want to pass to grep
. In /bin/sh
, you can use "$(printf \\e)"
or type a literal escape character.
With the GNU grep -o
option, the following snippet filters red text, assuming that it starts with the escape sequence \e[31m
, ends with either \e[0m
or \e[30m
on the same line, and contain no embedded escape sequence.
grep -Eo $'\e\\[31m[^\e]*\e\\[[03]?m'
The following awk
snippet extracts red text, even when it's multiline.
awk -v RS='\033' '
match($0, /^\[[0-9;]*m/) {
color = ";" substr($0, 2, RLENGTH-2) ";";
$0 = substr($0, RLENGTH+1);
gsub(/(^|;)0*[^03;][0-9]*($|;)/, ";", color);
red = (color ~ /1;*$/)
}
red'
Here's a variation which retains the color-changing commands, which could be useful if you're filtering multiple colors (here red and magenta).
awk -v RS='\033' '
match($0, /^\[[0-9;]*m/) {
color = ";" substr($0, 2, RLENGTH-2) ";";
printf "\033%s", substr($0, 1, RLENGTH);
$0 = substr($0, RLENGTH+1);
gsub(/(^|;)0*[^03;][0-9]*($|;)/, ";", color);
desired = (color ~ /[15];*$/)
}
desired'
Best Answer
Use
grep
like this:That long list of options to
grep
means-v
Invert the sense of the match, i.e. look for lines not matching.-x
When matching a pattern, require that the pattern matches the whole line, i.e. not just anywhere on the line.-F
When matching a pattern, treat it as a fixed string, i.e. not as a regular expression.-f
Read patterns from the given file (forbidden.txt
).Then pipe that to
sort
or whatever you want to do with it.