我在一个文件和一个数据文件(大小约为 3.2Gb)中有一个 id 列表,我想提取数据文件中包含 id 的行以及下一行。我做了以下事情:
grep -A1 -Ff file.ids file.data | grep -v "^-" > output.data
这有效,但也提取了不需要的子字符串,例如,如果 id 是EA4
它还拉出了线条EA40
.
所以我尝试使用相同的命令但添加-w
(--word-regexp
) 标记到第一个grep
匹配整个单词。然而,我发现我的命令现在运行了 >1 小时(而不是大约 26 秒),并且还开始使用 10 GB 的内存,所以我不得不终止这项工作。
为什么添加了-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 string file
只是寻找出现的情况string
在文件中但是grep -w -F string file
必须检查前后的每个字符string
也可以看看它们是否是单词字符。那是一个lot额外的工作和一个可能的实现是首先将行分成每个可能的非单词字符分隔的字符串,当然会有重叠,这样可能会占用大量内存,但不知道这是否是导致内存使用的原因。
无论如何,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 线。
请注意,无论有多少个,上面的方法都会起作用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
另外,您不需要将输出通过管道传输到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
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)