如何在包含另一个子字符串的文件中搜索子字符串

如何在包含另一个子字符串的文件中搜索子字符串

我想在包含另一个字符串的文件列表中搜索一个字符串。基本上,我必须获取包含第一个字符串的文件列表,然后在这些文件中搜索另一个字符串。

以下命令有帮助:

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 实用程序(您似乎已经拥有它,因为您已经在使用-rGNU 扩展)。

那是:

  • 使用-Zxargs -0来可靠地传递路径列表(在类 Unix 系统上,路径列表可以包含除 0 之外的任何字节值,但xargs不需要-0非常具体的格式)。
  • 如果第一个文件找不到任何文件,请使用-rforxargs来避免运行第二个文件(这里省略它没什么大不了的,它只会导致第二个文件grep 其空标准输入)。grepgrep
  • 选项应放在非选项参数之前。
  • 我们使用-H第二个选项grep来确保始终打印文件名(即使最终只有一个文件路径传递给它),以便我们知道匹配项在哪里。对于grep不支持 的实现-H,另一种方法是添加到要查找的/dev/null文件列表中。然后,传递多个文件名将始终打印该文件名。grepgrep

答案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对文件名进行排序并过滤掉双精度数(这实际上不是必需的)

相关内容