INPUT | grep --color=always "$string\{1,1\}"
...唉,$string 的每个实例都被突出显示。当我阅读文档时,“{1,1}”应确保仅突出显示第一个实例。或者有更好的工具吗?我无法使用 sed
INPUT | sed -r "s|$string|${red}$string${nrm}|I"
( ${red} 和 ${nrm} 只是颜色代码)
因为这里的 INPUT 是一个可能不区分大小写地找到的文件列表,如果我在 sed 中使用“I”选项,它会强制文件列表的大小写更改为命令输入的确切文本 - 即是的,我想搜索不区分大小写的文件,但无论文件列表中的字符串的大小写如何,都会不敏感地突出显示。
my_command *file_name*
...将使用“查找”来不区分大小写地查找文件,但在列表中我想强调:
file_name
FILE_nAME
file_NAME_this_file_has_a_long_file_name
...但仅限第一个实例(文件名可能包含输入字符串的重复项)。因此,在上面的最后一行中,“file_NAME”被突出显示,但“file_name”则没有突出显示。
grep 对于大小写问题没有问题,但 sed 有。 OTOH,sed 知道如何在一场比赛后停止,而 grep 似乎不知道。或者,还有更好的方法?
答案1
如果您grep
支持-P
类似 perl 的正则表达式,您可以这样做:
grep --color=always -P "^.*?\K\Q$string\E"
每行只能匹配一次,因为我们使用^
将匹配锚定在行的开头。接下来是.*?
匹配任意数量的字符尽可能少,并且$string
在\Q
/内,因此即使变量碰巧包含正则表达式运算符(除了),\E
它的内容也会按字面匹配。指定只有后面的内容才是ept,所以这里是彩色的。$string
\E
\K
K
或者你可以使用真实的东西而不必依赖任何 GNUism:
STRING=$string perl -ne 'print if s/\Q$ENV{STRING}\E/\e[31m$&\e[m/'
即使$string
包含也有效\E
。
答案2
我觉得你能如果使用模式替换,则使用sed
(匹配不区分大小写,但替换使用捕获的模式,而不是搜索到的模式):
INPUT | sed -r "s|(${string})|${red}\\1${nrm}|I"
另外,正如@don_crissti 注意到的,如果你想给全部的找到模式,您甚至不需要使用捕获组,您可以使用“无论它是什么”&
代码,这可能也稍微快一些:
INPUT | sed -r "s|${string}|${red}&${nrm}|I"
使用两个字符串而不是颜色代码似乎可以在我的 bash 上工作:
$ red="_RED_"
$ nrm="_NORM_"
$ string="amd"
$ echo -e "linux-5.4.0-amd-backfire.tar.bz2\\nThis is AMD Radeon\\nNames: Amdiranifani amd Jefri" \
| sed -r "s|(${string})|${red}\\1${nrm}|I"
linux-5.4.0-_RED_amd_NORM_-backfire.tar.bz2
This is _RED_AMD_NORM_ Radeon
Names: _RED_Amd_NORM_iranifani amd Jefri
第三行中的第二个“amd”不会被替换,所有其他替换都保留其原始大小写。
语法grep
意味着它将匹配第一个不断重复模式的一部分,因此在“bababa”中将仅匹配第一个“ba”,但在“baba___ba”中它将匹配第一个和第三个出现的情况。
显然grep 为所有的匹配,因此不能在本例中使用。