我有一个文件中的id列表和一个数据文件(大小约为3.2Gb),我想提取数据文件中包含id和下一行的行.我做了以下事情:
grep -A1 -Ff file.ids file.data | grep -v "^-" > output.data
这有效,但也提取了不需要的子串,例如,如果id是EA4,它也用EA40拉出线.
所以我尝试使用相同的命令,但将-w(–word-regexp)标志添加到第一个grep以匹配整个单词.但是,我发现我的命令现在运行了> 1小时(而不是~26秒)并且还开始使用10千兆字节的内存,所以我不得不杀死这份工作.
为什么添加-w会使命令变得如此缓慢并且内存占用?如何有效地运行此命令以获得所需的输出?谢谢
file.ids看起来像这样:
>EA4 >EA9
file.data如下所示:
>EA4 text data >E40 blah more_data >EA9 text_again data_here
output.data看起来像这样:
>EA4 text data >EA9 text_again data_here
grep -F字符串文件只是在文件中查找字符串的出现,但grep -w -F字符串文件必须检查字符串前后的每个字符,以查看它们是否是单词字符.这是一项额外的工作,其中一个可能的实现方法是首先将行分成每个可能的非单词字符分隔的字符串,当然这些字符串会重叠,这样可能占用大量内存,但如果这是导致记忆的话,那就是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
以上假设您的“数据”行不能以>开头.如果他们可以告诉我们如何识别数据线与id线.
请注意,无论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
此外,您不需要将输出传递给grep -v:
grep -A1 -Ff file.ids file.data | grep -v "^-" > output.data
只需在一个脚本中完成所有操作:
awk 'NR==FNR{ids[$0];next} /^>/{f=($1 in ids)} f && !/^-/' file.ids file.data