搜索多个字符串的方法:grep和egrep

17

假设我有几个字符串:str1、str2和str3。

  • 如何查找包含所有字符串的行?
  • 如何查找可以包含任何一个字符串的行?
  • 如何查找包含 str1 和 str2 或 str1 和 str3 的行,但不同时包含 str2 和 str3?
4个回答

30

这看起来像是三个问题。将这些表达式组合在一起的最简单方法是使用多个管道符。没有什么可耻的,特别是因为正则表达式(使用egrep)似乎要求您希望无序。

所以,按顺序:

  1. grep str1 | grep str2 | grep str3

  2. egrep '(str1|str2|str3)'

  3. grep str1 | egrep '(str2|str3)'

您可以使用egrep以无序的方式进行“and”形式,但我认为您会发现更容易记住使用管道过滤器的无序“and”,并使用正则表达式进行无序“or”。


3不符合“但不能同时”要求,但这个要求很难满足。您需要为交替的每一侧准备一个精心制作的前缀和后缀,以排除其他字符串在该行的任何其他位置出现。 - Michael Ekstrand
@Michael E:'但不是两者都'的部分是用斜体标出来,并在其后加上一个问号,因为当我编辑问题时,我不确定提问者想要什么。@Groundhog在我完善/修订问题之前就写了他的(很好的)答案,并且这个问题可能应该被删除。 - Jonathan Leffler
好的,我的评论因此不再相关。不过我会保留它,这样你的评论就不会失去上下文。我之前没有查看过问题的编辑历史。 - Michael Ekstrand
@groundhog:您有考虑过使用fgrep吗? - Jonathan Leffler
@Jonathan - 我相信 fgrep 只能使用固定参数字符串,而不能使用正则表达式。 - groundhog

8

由于grep不支持前瞻,因此您无法合理地执行“所有”或“这两个加上任意一个”的情况。建议使用Perl。对于“任意”情况,请使用egrep '(str1|str2|str3)' file

执行“所有”情况的不合理方法是:

egrep '(str1.*str2.*str3|str3.*str1.*str2|str2.*str1.*str3|str1.*str3.*str2)' file

例如,您可以构建排列组合。当然,这是一件荒谬的事情。

对于“这个加上那个”的情况,同样适用:

egrep '(str1.*(str2|str3)|(str2|str3).*str1)' file

5

grep -E --color "string1|string2|string3...."

例如,要查找我们的系统是否使用AMD(svm)或英特尔(vmx)处理器,并且如果它是64位(lm),则lm代表长模式-这意味着64位...。
命令示例:
grep -E --color "lm|svm|vmx" /proc/cpuinfo
-E必须用于查找多个字符串。

-1

个人而言,我会使用Perl来完成这个任务,而不是试图用grep拼凑出一些东西。

例如,对于第一个:

while (<FILE>)
{
   next if ! m/pattern1/;
   next if ! m/pattern2/;
   next if ! m/pattern3/;

   print $_;
}

3
问题不是什么是最好的工具来做那件事,而是如何使用grep来做到那件事。 - quosoo
3
答案是:“不要用grep,否则你会疯掉”。 - Paul Tomblin
7
@paul:抱歉,但“易于理解”和“Perl”不是可链接符号。 - groundhog
就此而言,完整/正确的perl一行代码(对于选项1,无管道)可以是perl -ne'print if / pat1 / && / pat2 / && / pat3 /'file1 file2 ..。是否容易理解取决于读者;但无论如何,现在至少可以剪切和粘贴了。 - michael
抱歉@Paul,感谢你的尝试,但如果你没有对所问问题的确切答案,但有一些有用的补充,那么最好是添加评论而不是回答一个没有人问的问题。对于像我这样的人,以及其他需要基于grep工作的人,由于某些原因,这个“答案”是无用的(例如我的系统甚至没有Perl)。我同意downvotes的观点,只是为了压制这个答案,但请不要把它当成个人攻击(顺便说一下,我没有downvote)。 - FractalSpace
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接