如何抓取同一行中存在的两个单词?

如何对包含两个输入单词的行进行 grep?我正在寻找包含两个单词的行,我该怎么做?我试过这样的烟斗:

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

只是在第一个管道命令之后卡住了。

为什么?

342084 次浏览

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

要想找到同一行中存在的两个单词,只需要:

grep "word1" FILE | grep "word2"

grep "word1" FILE将从 FILE 中打印所有包含 word1的行,然后 grep "word2"将打印包含 word2的行。因此,如果您使用一个管道来组合它们,它将显示同时包含 word1和 word2的行。

如果你只是想知道有多少行中有两个单词在同一行中,那么你可以这样做:

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

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

处方药

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

grep "word1" logs | grep "word2"

第一个 grep从文件‘ log’中查找带有‘ word1’的行,然后将这些行提供给第二个 grep,后者查找包含‘ word2’的行。

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

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

如果你知道 word1在 word2之前,你甚至不需要其他选项,常规的 grep就可以做到:

grep 'word1.*word2' logs

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

诊断

最初的剧本是:

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

这是一个奇怪的命令序列。第一个 grep将计算其标准输入中出现“ word1”的次数,并在其标准输出中打印该数字。直到你指示 EOF (例如输入 Control-D) ,它会一直在那里,等待你输入一些东西。第二个 grep在目录 logs下的文件(如果是文件,则在文件 logs中)中递归搜索“ word2”。或者,在我的例子中,它会失败,因为在运行管道的地方既没有文件也没有名为 logs的目录。注意,第二个 grep根本不读取它的标准输入,因此管道是多余的。

使用 Bash 时,父 shell 会等待管道中的所有进程都退出,因此它会一直等待 grep -c完成,在指示 EOF 之前它不会这样做。因此,您的代码似乎卡住了。在 传家宝贝壳中,第二个 grep完成并退出,shell 再次提示。现在有两个进程正在运行,第一个是 grep,第二个是 shell,它们都试图从键盘读取,并且不能确定哪个进程获得任何给定的输入行(或任何给定的 EOF 指示)。

注意,即使输入数据作为第一个 grep的输入,也只能得到输出中显示的包含“ word2”的任何行。


脚注:

有一次,答案是:

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

这引发了下面的评论。

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

grep "word1" logs | grep "word2"

如果您想要计算出现的次数,那么在第二个 grep 上放一个“-c”。

你可以试试下面的命令

cat log|grep -e word1 -e word2

你可以用 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 更慢。

使用 grep:

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

或者你可以使用:

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

git grep

下面是使用 git grep结合使用 布尔型表达式的多个模式的语法:

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

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

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

在工作目录中搜索不由 Git 管理的文件。

检查 man git-grep寻求帮助。

参见: