我正在执行这样的嵌套 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的? ”
使用“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)
(我假设您希望第二个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 实现nextfile
(nextfile
然后是空操作)。如果您知道您的awk
实现支持nextfile
,则可以将其简化为:
find . -type f -exec awk 'tolower($0) ~ /some string/ && /other string/ {
print FILENAME; nextfile}' {} +
Run Code Online (Sandbox Code Playgroud)
使用grep
PCRE 支持构建的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 -rlP
为pcregrep -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)