嵌套的管道 grep 结果是一个字符串,上面写着“(标准输入)”

OMA*_*OMA 6 grep pipe

我正在执行这样的嵌套 grep:

grep -ir "Some string" . |grep "Another string I want to find in the other grep's results"
Run Code Online (Sandbox Code Playgroud)

这完全按预期工作(我也从第二个 grep 过滤的第一个 grep 中获得了结果),但是一旦我添加了一个“-l”选项,所以我只能从第二个 grep 中获取文件列表,我不什么都得不到。

grep -ir "Some string" . |grep -l "Another string I want to find in the other grep's results"
Run Code Online (Sandbox Code Playgroud)

这导致以下输出:

(标准输出)

我想当我只想要文件列表时管道不起作用。任何替代方案?

Kus*_*nda 16

-l选项grep将使实用打印包含指定模式的文件的唯一名称。我系统上的手册对这个选项做了以下说明:

只有包含选定行的文件名被写入标准输出。grep 只会搜索文件,直到找到匹配项,从而降低搜索成本。每个搜索的文件都会列出一次路径名。如果搜索标准输入,则写入字符串“(标准输入)”。

由于grep管道中的第二个是从标准输入读取,而不是从文件中读取,因此除了到达其标准输入流之外,它不知道数据来自何处。这就是为什么它返回文本字符串(standard input)(不是(standard output)问题中所写的)。这是尽可能接近比赛所在的位置。

为了在这两种模式中的第一组合grep(这的确有关于哪些文件它在寻找知识),请参阅“如何使用多个和模式运行grep的?


Bri*_*SP2 5

使用“cut”删除“:”之后的字符串,然后您将获得文件部分(假设文件路径不包含冒号或换行符并且不匹配第二个模式本身)。

grep -ir "Some string" . |grep "Another string I want to find in the other grep's results" | cut -d ":" -f 1
Run Code Online (Sandbox Code Playgroud)

在重复的情况下使用“uniq”

grep -ir "string1" . | grep "string2" | cut -d: -f1 | uniq
Run Code Online (Sandbox Code Playgroud)


Sté*_*las 5

(我假设您希望第二个grep匹配行的内容而不是文件名或两者都按照您的方法进行)

POSIXly:

find . -type f -exec awk '
  FNR == 1 {found = 0}
  !found && tolower($0) ~ /some string/ && /other string/ {
    print FILENAME
    found = 1
    nextfile
  }' {} +
Run Code Online (Sandbox Code Playgroud)

业务found是针对尚不支持的 awk 实现nextfilenextfile然后是空操作)。如果您知道您的awk实现支持nextfile,则可以将其简化为:

 find . -type f -exec awk 'tolower($0) ~ /some string/ && /other string/ {
    print FILENAME; nextfile}' {} +
Run Code Online (Sandbox Code Playgroud)

使用grepPCRE 支持构建的GNU ,因为您希望一个匹配不区分大小写而不是另一个:

grep -rlP '^(?=.*(?i:some string))(?=.*other string)' .
Run Code Online (Sandbox Code Playgroud)

(?=...)是一个perl先行运营商。(?i:pattern)打开不区分大小写匹配pattern唯一。所以这里我们在行 ( ^)的开头进行匹配,前提是它后跟任意数量的字符 ( .*) 后跟some string(不区分大小写)并且它(行的开头)后跟任意数量的字符和other string(区分大小写)。

如果您grep不支持-P,您可以使用pcregrep命令代替(替换grep -rlPpcregrep -rl),或者如果模式不重叠,您可以执行以下操作:

grep -rl -e '[sS][oO][mM][eE] [sS][tT][rR][iI][nN][gG].*other string' \
         -e 'other string.*[sS][oO][mM][eE] [sS][tT][rR][iI][nN][gG]' .
Run Code Online (Sandbox Code Playgroud)

或者,如果您不关心两个匹配项都不区分大小写:

grep -ril -e 'some string.*other string' \
          -e 'other string.*some string' .
Run Code Online (Sandbox Code Playgroud)