如何grep同一行上存在的两个单词?

时间:2011-06-25 21:36:10

标签: grep

如何在线上包含两个输入字的行?我正在寻找包含两个单词的行,我该怎么做?我试过像这样的管道:

grep -c "word1" | grep -r "word2" logs

它只是在第一个管道命令之后停留。

为什么?

8 个答案:

答案 0 :(得分:141)

为什么通过-c?这只会显示比赛的数量。同样,没有理由使用-r。我建议你阅读man grep

要在同一行上找到2个单词,只需执行以下操作:

grep "word1" FILE | grep "word2"

grep "word1" FILE将从FILE中打印出包含word1的所有行,然后grep "word2"将打印包含word2的行。因此,如果使用管道组合这些,它将显示包含word1和word2的行。

如果您只想计算同一行上2个单词的行数,请执行:

grep "word1" FILE | grep -c "word2"

另外,要解决您的问题,为什么会卡住:在grep -c "word1"中,您没有指定文件。因此,grep期望来自stdin的输入,这就是它似乎挂起的原因。您可以按 Ctrl + D 发送EOF(文件结束),以便退出。

答案 1 :(得分:58)

处方

问题中一个简单的命令重写是:

grep "word1" logs | grep "word2"

第一个grep从文件'logs'中找到带有'word1'的行,然后将其输入到第二个grep中,查找包含'word2'的行。

但是,没有必要使用这样的两个命令。您可以使用扩展的grepgrep -Eegrep):

grep -E 'word1.*word2|word2.*word1' logs

如果你知道'word1'会在行上的'word2'之前,你甚至不需要替代方案,而常规grep会这样做:

grep 'word1.*word2' logs

'one command'变体的优点是只有一个进程在运行,因此包含'word1'的行不必通过管道传递给第二个进程。这有多重要取决于数据文件的大小以及多少行匹配'word1'。如果文件很小,性能可能不是问题,运行两个命令就可以了。如果文件很大但只有几行包含'word1',则管道上传递的数据不会太多,并且使用两个命令就可以了。但是,如果文件很大并且经常出现'word1',那么您可能会将大量数据传递到管道中,而单个命令可以避免这种开销。相反,正则表达式更复杂;您可能需要对其进行基准测试以找出最佳效果 - 但前提是性能确实很重要。如果您运行两个命令,则应该在第一个grep中选择不常出现的单词,以最大限度地减少第二个处理的数据量。

诊断

初始脚本是:

grep -c "word1" | grep -r "word2" logs

这是一个奇怪的命令序列。第一个grep将计算其标准输入上“word1”的出现次数,并在其标准输出上打印该数字。直到您指示EOF(例如,通过键入 Control-D ),它将坐在那里,等待您输入内容。第二个grep在目录logs下面的文件中对'word2'进行递归搜索(或者,如果它是文件,则在文件logs中)。或者,在我的情况下,它将失败,因为既没有文件也没有名为logs的目录,我正在运行管道。请注意,第二个grep根本不读取其标准输入,因此管道是多余的。

使用Bash,父shell等待直到管道中的所有进程都退出,所以它等待grep -c完成,直到你指示EOF才会这样做。因此,您的代码似乎陷入困境。使用Heirloom Shell,第二个grep完成并退出,shell再次提示。现在你有两个进程正在运行,第一个grep和shell,它们都试图从键盘读取,并且不确定哪一个获得任何给定的输入行(或任何给定的EOF指示)。

请注意,即使您输入数据作为第一个grep的输入,您也只能获得输出中包含“word2”的所有行。


脚注:

曾经使用的答案是:

grep -E 'word1.*word2|word2.*word1' "$@"
grep 'word1.*word2' "$@"

这引发了以下评论。

答案 2 :(得分:8)

你可以使用awk。像这样...

cat <yourFile> | awk '/word1/ && /word2/'

订单并不重要。所以如果你有一个文件......

名为file1的文件包含:

word1 is in this file as well as word2
word2 is in this file as well as word1
word4 is in this file as well as word1
word5 is in this file as well as word2

然后,

/tmp$ cat file1| awk '/word1/ && /word2/'

将导致,

word1 is in this file as well as word2
word2 is in this file as well as word1
是的,awk比较慢。

答案 3 :(得分:7)

主要问题是你没有提供任何输入的第一个grep。您需要重新排序命令,如

grep "word1" logs | grep "word2"

如果你想计算出现次数,那就在第二个grep上加一个'-c'。

答案 4 :(得分:5)

你试试下面的命令

cat log|grep -e word1 -e word2

答案 5 :(得分:1)

grep word1 file_name | grep word2

这对我来说似乎是最简单的方式

答案 6 :(得分:0)

使用grep:

grep -wE "string1|String2|...." file_name

或者您可以使用:

echo string | grep -wE "string1|String2|...."

答案 7 :(得分:-1)

git grep

以下是使用git grep使用 Boolean 表达式组合多个模式的语法:

git grep -e pattern1 --and -e pattern2 --and -e pattern3

上述命令将一次打印与所有模式匹配的行。

如果文件不受版本控制,请添加--no-index参数。

  

搜索当前目录中不由Git管理的文件。

检查man git-grep寻求帮助。

另见: