Lix*_*Lix 32 shell grep bash pipe
我试图让每个 grep 命令以不同的颜色突出显示其结果。我可以用这样的一行手动完成:
ls -l GREP_COLORS='mt=01;32' grep c | GREP_COLORS='mt=01;31' grep o | GREP_COLORS='mt=01;34' grep n | GREP_COLORS='mt=01;36' grep f
Run Code Online (Sandbox Code Playgroud)

每个c字符将以绿色突出显示,每个o字符将以红色突出显示,等等......
要使此示例正常工作,您需要确保始终使用
--color=alwaysgrep 命令。我已经在我的.bashrc所以 grep 中设置了它总是有颜色:
export GREP_OPTIONS='--color=always'
我试图完成的是用别名包装这个功能,所以我每次grep都可以调用并拥有不同的GREP_COLORS值。我理解为每个新的管道 grep 考虑多个 shell,我试图通过创建一些文件(每种颜色一个)来解决这个问题,以表明它们已经被使用。
我做了一些尝试,但奇怪的是,这个似乎是“最好的”。我有这个.bashrc:
alias mg="mygrep"
mygrep(){
# define possible colors
COLORS=("01;32" "01;31" "01;34" "01;36")
COUNTER=0
NUM=0
# as long as the color has already been used, keep searching
while [ -f /home/lior/Desktop/mygrep_$NUM ]; do
# get a random index
let NUM=`shuf --input-range=0-$(( ${#COLORS[*]} - 1 )) | head -1`
wait ${!}
$(( COUNTER+=1 ))
if [ "$COUNTER" -ge ${#COLORS[@]} ]; then
# remove all color locks
rm /home/lior/Desktop/mygrep_*
wait ${!}
fi
done
# mark this color as used
touch /home/lior/Desktop/mygrep_$NUM
wait ${!}
# lets go!
GREP_COLORS="mt=${COLORS[$NUM]}" grep "$@"
}
Run Code Online (Sandbox Code Playgroud)
我像这样使用这个别名:
ll | mg c | mg o | mg n | mg f
Run Code Online (Sandbox Code Playgroud)
结果很酷。然而,有一些错误每次都略有不同。下面是几个截图:
看起来当 shell 通过每个管道命令时,前一个函数还没有完成它的执行。它试图删除不再存在的文件。我不确定其他command not found错误来自哪里。
如您所见,我已经输入了一些wait命令来尝试完成文件操作,但这似乎不太好。我已经尝试过的另一件事是使用共享内存,/dev/shm但它产生了类似的结果。
我将如何获得我想要的结果?
笔记:
我正在寻找简单地包装 grep 命令的答案,因为它有很多我想要使用的功能,并打算在管道之间插入其他逻辑,所以我不想一次提供所有搜索词。我也不是在寻找其他“类似 grep”的工具。抱歉,@terdon已经发布了一个很棒的 perl 建议。
这是一种不同的方法。我有一个小的 Perl 脚本,我已经在另一个答案中发布了它,它将以不同的颜色突出显示用户提供的模式。脚本的稍微修改版本将如下所示grep:
#!/usr/bin/env perl
use Getopt::Std;
use strict;
use Term::ANSIColor;
my %opts;
getopts('hic:l:',\%opts);
if ($opts{h}){
print<<EoF;
Use -l to specify the pattern(s) to highlight. To specify more than one
pattern use commas.
-l : A Perl regular expression to be colored. Multiple expressions can be
passed as comma separated values: -l foo,bar,baz
-i : makes the search case sensitive
-c : comma separated list of colors;
EoF
exit(0);
}
my $case_sensitive=$opts{i}||undef;
my @color=('bold red','bold blue', 'bold yellow', 'bold green',
'bold magenta', 'bold cyan', 'yellow on_blue',
'bright_white on_yellow', 'bright_yellow on_red', 'white on_black');
if ($opts{c}) {
@color=split(/,/,$opts{c});
}
my @patterns;
if($opts{l}){
@patterns=split(/,/,$opts{l});
}
else{
$patterns[0]='\*';
}
# Setting $| to non-zero forces a flush right away and after
# every write or print on the currently selected output channel.
$|=1;
while (my $line=<>)
{
my $want=0;
for (my $c=0; $c<=$#patterns; $c++){
if($case_sensitive){
if($line=~/$patterns[$c]/){
$line=~s/($patterns[$c])/color("$color[$c]").$1.color("reset")/ge;
$want++;
}
}
else{
if($line=~/$patterns[$c]/i){
$line=~s/($patterns[$c])/color("$color[$c]").$1.color("reset")/ige;
$want++;
}
}
}
print STDOUT $line if $want>0;
}
Run Code Online (Sandbox Code Playgroud)
如果将该脚本保存在cgrep某个位置PATH并使其可执行,则最多可以指定 10 种不同的模式,每种模式都将以不同的颜色打印:

$ cgrep -h
Use -l to specify the pattern(s) to highlight. To specify more than one
pattern use commas.
-l : A Perl regular expression to be colored. Multiple expressions can be
passed as comma separated values: -l foo,bar,baz
-i : makes the search case sensitive
-c : comma separated list of colors;
Run Code Online (Sandbox Code Playgroud)
grep管道中的每次调用都在单独的 shell 中运行,因此您需要在它们之间传递一些状态。以下解决方案是一种粗略的处理方法,使用一个保留颜色索引的文件和一个锁定文件来确保同时调用不会读取相同的值:
#!/usr/bin/env bash
color_index_file=~/.gitcolor
color_index_lock_file=/tmp/$(basename $0)
colors=()
for index in {31..34}
do
colors+=("01;$index")
done
until mkdir "$color_index_lock_file" 2>/dev/null
do
:
done
color_index=$(($(cat "$color_index_file" || echo 0) + 1))
if [[ $color_index -ge ${#colors[@]} ]]
then
color_index=0
fi
printf "$color_index" > "$color_index_file"
rmdir "$color_index_lock_file"
GREP_COLORS="mt=01;${colors[$color_index]}" grep --color=always "$@"
Run Code Online (Sandbox Code Playgroud)
测试假设您已命名您的副本cgrep并将其放在您的PATH:
echo foobarbaz | cgrep foo | cgrep bar | cgrep baz
Run Code Online (Sandbox Code Playgroud)