我对 m 个文件有 n 个单独的非固定 grep。我只需要知道每个文件中是否至少有 1 个匹配项,但每个模式都需要这个。我目前制作了 n 个单独的 grep,以便以后可以将它们全部合并,但它非常慢并且有些文件很大。
有没有办法替换这些不需要我读取所有文件 n 次(只要我可以将模式(不匹配)匹配到包含匹配项的文件,就不需要是单独的文件)。grep -f 看起来很有希望,但它显示匹配任何模式的文件,而不是匹配每个模式的文件。
稍后合并到 1 个大文件中的内容:
grep -liE pattern1 file_glob* > temp_pattern1.txt && sed s/^/escapedpattern1 / temp_pattern1.txt
grep -liE pattern2 file_glob* > temp_pattern2.txt && sed s/^/escapedpattern2 / temp_pattern2.txt
...
grep -liE patternN file_glob* > temp_patternN.txt && sed s/^/escapedpatternN / temp_patternN.txt
temp_pattern1.txt
pattern1 /path/to/file1
pattern1 /path/to/file2
pattern1 /path/to/file3
temp_pattern2.txt
pattern2 /path/to/file1
pattern2 /path/to/file3
...
temp_patternN.txt
pattern N /path/to/fileM
如果你想使用
grep
,你能做的最好的就是使用在第一次匹配时停止读取当前输入文件的-m 1
选项。grep
您仍然会多次读取每个输入文件(每个模式一次),但它应该更快(除非匹配在文件的最后一行或附近)。例如
注意:
$p+1
存在是因为 bash 数组从零开始。+1 使 temp_patterns 文件从 1 开始。如果您使用像或之类的脚本语言,您可以做您想做的事。例如,下面的 perl 脚本只读取每个输入文件一次,并针对尚未在该文件中看到的每个模式检查每一行。它跟踪已经在特定文件中看到的模式(使用数组),并且还注意到何时在文件中看到了所有可用模式(也使用)并在这种情况下关闭当前文件。
awk
perl
@seen
@seen
该
if (eof || $#seen == $#patterns)
行测试当前文件上的 eof(文件结尾)或者我们是否已经看到当前文件中的所有可用模式(即,@seen 中的元素数是否等于 @patterns 中的元素数)。在这两种情况下,我们都希望将 @seen 数组重置为空,以便为下一个输入文件做好准备。
在后一种情况下,我们还想提前关闭当前输入文件——我们已经看到了我们想要在其中看到的所有内容,无需继续读取和处理文件的其余部分。
顺便说一句,如果您不希望创建空文件(即当模式不匹配时),请取消注释
next unless @{ $matches[$i] }
输出 for 循环中的行。如果您不需要或不需要临时文件,并且只想将所有匹配项输出到一个文件,请将最终输出 for 循环替换为:
并将输出重定向到文件。
顺便说一句,如果要添加模式在文件中首次出现的行号,请更改:
至
$.
是一个内置的 perl 变量,它保存输入的当前行号<>
。ARGV
只要当前文件 ( ) 关闭,它就会重置为零。