我知道有一些类似的问题已经得到了回答,但我还没有找到我想要的东西(并尝试了所提出的解决方案的变体)。希望这是一个简单的问题。
我有一个带有10列和大约50万行的制表符分隔文件(file.txt),其简化形式如下所示:
ID Col1 Col2 Col3
a 4 2 8
b 5 6 1
c 8 4 1
d 3 5 9
e 8 5 2
我想删除所有行,例如“b”和“d”出现在第一个(ID)列中。我想要的输出是:
ID Col1 Col2 Col3
a 4 2 8
c 8 4 1
e 8 5 2
在输出文件中保留ID的顺序非常重要。
实际上,我想删除大约100,000行。因此,我有一个参考文件(referencefile.txt),列出了我想从file.txt中删除的所有ID。在这个例子中,参考文件在连续的行上只包含“b”和“d”。
我现在正在使用grep,虽然它有效,但它确实很慢。
grep -v -f referencefile.txt file.txt
有没有办法使用awk或sed(或其他任何东西)来加速这个过程?
非常感谢。
AB
答案 0 :(得分:2)
使用awk
:
awk 'FNR>1 && ($1 == "b" || $1 == "d"){ next } 1' infile
# OR
awk 'FNR>1 && $1 ~ /^([bd])$/{ next } 1' infile
# To exclude line from infile, where list of ids from id_lists
# exists in first field of infile
awk 'FNR==NR{ids[$1];next}FNR>1 && ($1 in ids){next}1' id_lists infile
# To include line from infile, where list of ids from id_lists
# exists in first field of infile
awk 'FNR==NR{ids[$1];next}FNR==1 || ($1 in ids)' id_lists infile
测试结果:
<强>输入强>
$ cat infile
ID Col1 Col2 Col3
a 4 2 8
b 5 6 1
c 8 4 1
d 3 5 9
e 8 5 2
<强>输出强>
$ awk 'FNR>1 && $1 ~ /^([bd])$/{ next } 1' infile
ID Col1 Col2 Col3
a 4 2 8
c 8 4 1
e 8 5 2
$ awk 'FNR>1 && ($1 == "b" || $1 == "d"){ next } 1' infile
ID Col1 Col2 Col3
a 4 2 8
c 8 4 1
e 8 5 2
但&#34; b&#34;和&#34; d&#34;是为了说明的目的,我实际上有 我需要移除大约100,000个ID。所以我想要所有这些ID 列在单独的文件(referencefile.txt)
如果您的文件包含下面的ID列表,那么
排除ID列表
$ cat id_lists
a
b
$ awk 'FNR==NR{ids[$1];next}FNR>1 && ($1 in ids){next}1' id_lists infile
ID Col1 Col2 Col3
c 8 4 1
d 3 5 9
e 8 5 2
要包含ID列表
$ awk 'FNR==NR{ids[$1];next}FNR==1 || ($1 in ids)' id_lists infile
ID Col1 Col2 Col3
a 4 2 8
b 5 6 1
答案 1 :(得分:0)
有很多方法可以加快grep
本身的速度。
我建议:
-F
将-f referencefile.txt
中的输入视为固定字符串而不是正则表达式。
-w
匹配单词
可能LC_ALL=C
- 使用LC_ALL
环境变量来指示grep使用ascii而不是UTF-8