我想在包含另一个字符串的文件列表中搜索一个字符串。基本上,我必须获取包含第一个字符串的文件列表,然后在这些文件中搜索另一个字符串。
以下命令有帮助:
grep -ril './' -e "first_string" | xargs grep -i "second_string"
命令的前半部分给出了包含以下内容的文件列表第一个字符串。
r
- 递归地进入目录
i
- 要搜索的字符串不区分大小写
l
- 列出匹配的文件
后半部分将采用这些文件路径并运行第二部分grep
来搜索文件是否有第二个字符串。
在这里,我们需要xargs
获取这些文件并执行第二个grep
命令。
答案1
你宁愿想要:
grep -rilZ 'first_string' . | xargs -r0 grep -Hi 'second_string'
假设 GNU 实用程序(您似乎已经拥有它,因为您已经在使用-r
GNU 扩展)。
那是:
- 使用
-Z
和xargs -0
来可靠地传递路径列表(在类 Unix 系统上,路径列表可以包含除 0 之外的任何字节值,但xargs
不需要-0
非常具体的格式)。 - 如果第一个文件找不到任何文件,请使用
-r
forxargs
来避免运行第二个文件(这里省略它没什么大不了的,它只会导致第二个文件grep 其空标准输入)。grep
grep
- 选项应放在非选项参数之前。
- 我们使用
-H
第二个选项grep
来确保始终打印文件名(即使最终只有一个文件路径传递给它),以便我们知道匹配项在哪里。对于grep
不支持 的实现-H
,另一种方法是添加到要查找的/dev/null
文件列表中。然后,传递多个文件名将始终打印该文件名。grep
grep
答案2
find . | perl -ne 'open($fh, $_); $s1=0; $s2=0; while($line = <$fh>) { $s1=1 if($line=~/string 1/); $s2=1 if($line=~/string 2/); } ; print $_ if($s1==1 and $s2 ==1); close $fh;' | sort | uniq
(看起来有点长,但这全部都在一行)
编辑:一些解释:
find . |
将要搜索的目录中的所有文件列表 (.
) 发送到下一个命令 (perl
)perl -ne 'COMMANDS'
循环遍历它在 STDIN 上接收到的所有行(即所有文件)并COMMANDS
在每个行上运行。每个文件的名称每次都会以$_
open($fh, $_); COMMANDS; close $fh;
打开一个文件,将其绑定到 filehandle$fh
,运行COMMANDS
并再次关闭它。$s1=0; $s2=0;
每次下一个文件启动时,这些变量都会再次设置为 0(如果我们在当前文件中找到字符串,则将其设置为 1)while($line = <$fh>) { COMMANDS } ;
COMMANDS
在文件中的每一行运行。$s1=1 if($line=~/string 1/); $s2=1 if($line=~/string 2/);
如果string 1
在当前文件中找到$s1
就会变成1,同样的$s2
print $_ if($s1==1 and $s2 ==1);
如果找到字符串则打印文件名。| sort | uniq
对文件名进行排序并过滤掉双精度数(这实际上不是必需的)