我将 egrep ( grep -E
) 与 PATTERN 文件一起使用。( -f path/to/file
).
这是在文本流的无限循环中完成的。这意味着我无法一次累积并将所有输入传递给 grep(如*.log
)。
有没有办法让 grep “保存”它从 PATTERN 文件构建的 NFA 以供下次运行使用?
我已经搜索过谷歌并阅读了文档,但没有运气。
我会试着多解释一下。我需要使用正则表达式来定位固定数量的字符串(这不是问题的一部分,但可以随意提出其他建议),例如 IP 地址、域等。搜索是在来自互联网的提要上完成的。您可以将其视为文本流。我不能grep
在所有输入上使用,因为它是一个流。我可以累积一大块流并grep
在其上使用(因此不在grep
每一行上使用),但这也是有限的(假设为 30 秒)。
我知道grep
正在从其所有模式(在我的情况下是从文件)构建 NFA。所以我的问题是:我可以告诉grep
为下次运行保存该 NFA,因为它不会改变吗?这将节省我每次构建 NFA 的时间。
Sté*_*las 14
不,没有这样的事情。一般来说,启动grep
(fork 一个新进程、加载可执行文件、共享库、动态链接...)的成本会比编译正则表达式要大得多,所以这种优化没有多大意义。
虽然看到为什么将 1250 个字符串与 90k 模式匹配这么慢?关于某些版本的 GNUgrep
中的一个错误,该错误会使大量正则表达式变得特别慢。
可能在这里,您可以grep
通过将块提供给同一个grep
实例来避免多次运行,例如将其用作协同进程并使用标记来检测结束。使用zsh
和 GNUgrep
以及awk
除mawk
以下之外的其他实现:
coproc grep -E -f patterns -e '^@@MARKER@@$' --line-buffered
process_chunk() {
{ cat; echo @@MARKER@@; } >&p & awk '$0 == "@@MARKER@@"{exit};1' <&p
}
process_chunk < chunk1 > chunk1.grepped
process_chunk < chunk2 > chunk2.grepped
Run Code Online (Sandbox Code Playgroud)
虽然用awk
或perl
代替做整个事情可能更简单。
但是,如果您不需要将grep
输出放入不同块的不同文件中,您可以随时执行以下操作:
{
cat chunk1
while wget -qO- ...; done # or whatever you use to fetch those chunks
...
} | grep -Ef patterns > output
Run Code Online (Sandbox Code Playgroud)