使用-w(--word-regexp)标志为什么grep如此缓慢和内存密集?

Chr*_*nds 6 unix bash shell awk grep

我有一个文件中的id列表和一个数据文件(大小约为3.2Gb),我想提取数据文件中包含id和下一行的行.我做了以下事情:

grep -A1 -Ff file.ids file.data | grep -v "^-" > output.data
Run Code Online (Sandbox Code Playgroud)

这有效,但也提取了不需要的子串,例如,如果id EA4也被拉出线EA40.

所以我尝试使用相同的命令,但将-w(--word-regexp)标志添加到第一个grep以匹配整个单词.但是,我发现我的命令现在运行了> 1小时(而不是~26秒),并且还开始使用10千兆字节的内存,所以我不得不杀死这份工作.

为什么添加-w使命令如此缓慢和内存占用?如何有效地运行此命令以获得所需的输出?谢谢

file.ids 看起来像这样:

>EA4
>EA9
Run Code Online (Sandbox Code Playgroud)

file.data 看起来像这样:

>EA4 text
data
>E40 blah
more_data
>EA9 text_again
data_here
Run Code Online (Sandbox Code Playgroud)

output.data 看起来像这样:

>EA4 text
data
>EA9 text_again
data_here
Run Code Online (Sandbox Code Playgroud)

Ed *_*ton 9

grep -F string file只是string在文件中查找出现的内容,但grep -w -F string file必须检查每个字符之前和之后string,看它们是否是单词字符.这是一个很多额外的工作和一个可能的实现,这将是先单独的行与课程的重叠每一个可能的非单词字符分隔的字符串,这样可能会占用大量的内存,但IDK的,如果这是什么导致你的记忆用法与否.

在任何情况下,grep只是这个工作的错误工具,因为你只想匹配输入文件中的特定字段,你应该使用awk:

$ awk 'NR==FNR{ids[$0];next} /^>/{f=($1 in ids)} f' file.ids file.data
>EA4 text
data
>EA9 text_again
data_here
Run Code Online (Sandbox Code Playgroud)

以上假设您的"数据"行无法启动>.如果他们可以告诉我们如何识别数据线与id线.

请注意,无论data行之间有多少id行,即使有0或100 ,上述内容也会起作用:

$ cat file.data
>EA4 text
>E40 blah
more_data
>EA9 text_again
data 1
data 2
data 3

$ awk 'NR==FNR{ids[$0];next} /^>/{f=($1 in ids)} f' file.ids file.data
>EA4 text
>EA9 text_again
data 1
data 2
data 3
Run Code Online (Sandbox Code Playgroud)

此外,您不需要将输出传递给grep -v:

grep -A1 -Ff file.ids file.data | grep -v "^-" > output.data
Run Code Online (Sandbox Code Playgroud)

只需在一个脚本中完成所有操作:

awk 'NR==FNR{ids[$0];next} /^>/{f=($1 in ids)} f && !/^-/' file.ids file.data
Run Code Online (Sandbox Code Playgroud)