说我有以下文件:

$ cat test

test line 1
test line 2
line without the search word
another line without it
test line 3 with two test words
test line 4


默认情况下,grep返回包含搜索项的每一行:

$ grep test test

test line 1
test line 2
test line 3 with two test words
test line 4


--color参数传递给grep将使其突出显示与搜索表达式匹配的行部分,但仍仅返回包含该表达式的行。有没有办法让grep输出源文件中的每一行,但突出显示匹配项?没有匹配项)是:

$ grep -B 9999 -A 9999 test test




如果grep无法完成此操作,是否还有另一个命令行工具可以提供相同的功能?我弄弄过ack,但似乎也没有选择。

评论

可能的跨站点重复项:stackoverflow.com/questions/981601/…两者的最高答案是相同的。

您可以使用-C 9999代替-A 9999 -B 9999.我总是这样做:grep -C 9999模式文件

尝试sed。例如,以下是突出显示+返回退出代码的方法:askubuntu.com/a/1200851/670392

#1 楼

grep --color -E "test|$" yourfile


我们在这里所做的与$模式和测试模式相匹配,显然$没有任何要着色的颜色,因此只有测试模式才会变色。 -E只是打开扩展的正则表达式匹配。

您可以像这样轻松地创建函数:

highlight () { grep --color -E "|$" "${@:1}" ; }


评论


真是太厉害了!

– gvkv
2010年8月12日下午3:09

并作为一个函数:Highlight(){grep --color -E“ $ 1 | $” $ 2; }。用法:突出显示测试您的文件

– Stefan Lasiewski
2010-10-14 3:48

更好的方法是:Highlight(){grep --color -E“ $ 1 | $”“ $ @”}允许文件名中带有空格的文件和多个文件。

–迈克·德西蒙(Mike DeSimone)
2011年7月24日在5:34

@MikeDeSimone-但是文件中也将包含“ $ 1”。使用高亮(){grep --color -E“ $ 1 | $”“ $ {@:1}”}

–克里斯唐(Chris Down)
11年11月17日在11:48

我用bash想到了这个$ {@:2},因为您不希望在列表文件中重复第一个参数来检查。 Highlight(){grep --color -E-“ $ 1 | \ $”“ $ {@:2}” ;; }。注意-也表示用破折号表示参数已完成,因此,如果您搜索模式行-则该行仍然有效。

–林奇
16-3-13在5:08



#2 楼

ack --passthru --color string file


对于Ubuntu和Debian,使用ack-grep代替ack

ack-grep --passthru --color string file


评论


哦,这在手册页中很明显;我瞎了。谢谢

– Michael Mrozek
2010年8月17日在20:03

grap的模式可以用--regexp字符串显式指定; ack / ack-grep等效项是--match字符串

–大黄
15年1月8日在17:46

用perl模拟ack --passthru:grep_passthrough(){! perl -ne“打印; \ $ e || = / $ @ /; END {{exit \ $ e}}”; }

–卢卡斯·西蒙(Lucas Cimon)
16 Mar 4 '16 at 17:58

ack --passthru也可以在流上使用!例如,ifconfig | ack --passthru inet

– honkaboy
16年6月16日,0:10



#3 楼

使用grep正确且可移植的另一种方法(除了使用两个正则表达式交替使用,如公认的答案一样)是通过null模式(以及分别为null字符串)。因为,按照标准:

-E
    Match using extended regular expressions. 
    [...] A null ERE shall match every line.




-F
    Match using fixed strings.
    [...] A null string shall match every line.


所以这只是运行问题/>
grep -E -e '' -e 'pattern' infile




grep -F -e '' -e 'string' infile


评论


或者只是grep -F -e''-e'string'。

–StéphaneChazelas
17年1月26日在23:14

它适用于GNU grep 2.25,busybox grep和传家宝工具。

–StéphaneChazelas
17年1月26日在23:25

好吧,我不好,seq 3 | grep -F -e''-e 2仅在2.27中输出2(和2.26,但不输出2.25,并且不在git头中)。仅带有-F(不带有-E或不带有)。 IOW,只有2.26和2.27似乎有此错误,并且只有-F。

–StéphaneChazelas
17年1月26日23:56



注意seq 3 | grep -F -e''-e''-e 2似乎在2.27上也能正常工作

–StéphaneChazelas
17年1月27日,0:03

此答案中给出的方法简单,正确,并且看起来非常快。就像您说的那样,它与-F自动配合使用,从而无需担心字符串中会出现什么字符。您可能要提到--color;由于此答案在页面上浮动(通过投票查看时),因此更多的人可能最终会在其他答案之前阅读它。

– Eliah Kagan
17年1月27日在5:12

#4 楼

我具有用于此类用途的以下功能:

highlight () {
    perl -pe "s//\e[1;31;43m$&\e[0m/g"
}


内部看起来很丑陋,它很好用且易于使用,就像这样:

cat some_file.txt | highlight some_word


,或者,例如,更真实一些的示例: (使用grep可能很难-我不确定)将13143(在\e[之后)更改为不同的值。到处都有使用的代码,但这是一个快速的介绍:1粗体显示文本,31使其变为红色,而43给出黄色背景。 3233将使用不同的颜色,4445将使用不同的背景:您明白了。如果您愿意,甚至可以使其闪烁(使用5。)这不使用任何特殊的Perl模块,Perl几乎无处不在,所以我希望它可以正常工作大约在任何地方。 grep解决方案非常聪明,但是grep上的--color开关并非在所有地方都可用。例如,我只是在运行bash,运行ksh的Solaris盒和运行zsh的本地Mac OS X机器上尝试了此解决方案。一切都很好。但是,Solaris使grep --color解决方案感到窒息。我工作的许多服务器。 (我忘记了为什么:我认为它与所需的Perl模块有关。)嵌入式系统,Linksys路由器等),我想说这是一个通用的解决方案。

评论


我喜欢此解决方案,因为它可以满足您的需求,而不是像grep这样的弯曲工具和更间接的现有工具。如果您要更改行为,它还为您提供了更大的灵活性。 (尽管只是一个注释,您可以使用带有相同SGR代码的env var GREP_COLORS使用grep更改颜色)。

–wardw
20/12/17在16:16



还需要注意的是,匹配后颜色将用\ e [0m重置,因此这还将清除输入流中所有现有的颜色。但是,grep也是如此。如果需要处理已着色的输入,则可以考虑使用终端控件tput smso和tput rmso来包装匹配文本。

–wardw
20 Dec 17 '20 at 16:20

#5 楼

代替使用Grep,可以使用Less:

less file


像这样搜索:/pattern输入

这将:


滚动到第一条匹配行
从那里开始输出每行
突出显示所有匹配项

滚动到下一条匹配行:n

滚动到上一个匹配行:N

切换突出显示:Esc u

如果您愿意,也可以更改突出显示颜色。

#6 楼

ripgrep
ripgrep--passthru参数一起使用:
rg --passthru pattern file.txt

它是最快的grepping工具之一,因为它是基于Rust的正则表达式引擎构建的,该引擎使用有限自动机,SIMD和积极的文字优化来进行搜索非常快。

--passthru-同时打印匹配和不匹配的行。
实现类似效果的另一种方法是修改模式以匹配空字符串。例如,如果您使用rg foo搜索,则使用rg "^|foo"代替,它将在搜索到的每个文件中发出每一行,但仅高亮显示foo。此标志启用相同的行为,而无需修改模式。


#7 楼

您可以尝试:

perl -MTERM::ANSIColor -nle '/pattern/ ? print colored($_, 'color') : print' test


但是,它不是很便携,即使安装了Perl,也可能需要下载另一个模块。此外,它将为整行着色,而不仅仅是搜索词。

#8 楼

到目前为止,没有给出的答案都提供了便携式解决方案。 perlackggrepgsedbash之类,但仅需要POSIX shell和POSIX强制实用程序sedprintf

grepc()
{
  pattern=
  shift
  esc=$(printf "3")
  sed 's"'"$pattern"'"'$esc'[32m&'$esc'[0m"g' "$@"
}




grepc string_to_search [file ...]


可以通过在sed命令参数中使用以下代码之一来调整突出显示颜色(此处32m为绿色):
30m black
31m red
33m yellow
34m blue
35m magenta
36m cyan
37m white
7m reverse video


1只要您的终端支持ANSI颜色转义序列。

#9 楼

对于GNU grep,有一种更简便的方法,但我认为它不是可移植的(即BSD grep):

在管道中: >
在文件上:

cat <file> | grep --color=always -z <query>

贷方在此处输入Cyrus的答案。

评论


这不是您(和Cyrus)所想的答案。它具有将整个文件视为一行的效果。因此,(1)如果文件很大,则可能会出现内存不足的情况;(2)如果文件根本不包含模式,则将不会输出任何内容。而且你是对的;它不是普遍可用的。 (但是再说一遍,--color也不是标准的。)

– G-Man说“恢复莫妮卡”
17年2月6日在4:43

支持什么版本的grep?在grep 2.5.4上,-z似乎不可用...

– Alex
17年6月29日在22:29

#10 楼

一个sed版本,
可同时在bashash上使用。

#11 楼

OP要求grep,这是我建议的内容;但经过努力解决sed的问题后,记录下来,这是一个简单的解决方案:

sed $'s/main/\E[31m&\E[0m/g' testt.c


main涂成红色。 br />
\E[31m:匹配的模式

\E[0m:一行中的所有单词,不仅是第一个单词

&是带有解释为转义字符的bash字符串/>

关于grep,它也可以使用/g(行首)而不是$'string'(行尾)来工作。例如:

cat testt.c | sed $'s/main/\E[31m&\E[0m/g'


为了显示这个我不推荐的疯狂别名,您甚至可以使用开放引号: br />
所有工作! :)如果您忘记关闭引号,请不要担心,bash会以“连续行字符”记住您。

#12 楼

如果您对grep的返回值感兴趣,那么GNU sed也是这样:
sed '/pattern/h; ${p;x;/./Q0;Q1}'
您可以在脚本行中添加修改,例如:
sed '/pattern/h; ${p;x;/./Q0;Q1}; s/pattern/<pattern>/g'
这将检查$是否出现在当前行上,并将其存储在保持缓冲区中。在文件末尾(p),打印最后一行(x),然后交换保留空间和模式空间(/./)。接下来,测试模式空间是否为空(0),如果它是非空的,则以代码q4​​312079q(Q0)退出,否则以代码1(Q1)退出。
另一种方法是/pattern/{:a $q1; n; ba},在检测到pattern后循环更改当前行可能会很棘手。