我有一个看起来像这个玩具示例的文件。我的实际文件有 400 万行,其中大约 10 行我需要删除。
ID Data1 Data2
1 100 100
2 100 200
3 200 100
ID Data1 Data2
4 100 100
ID Data1 Data2
5 200 200
我想删除除了第一行之外看起来像标题的行。
最终文件:
ID Data1 Data2
1 100 100
2 100 200
3 200 100
4 100 100
5 200 200
我怎样才能做到这一点?
答案1
您可以使用
sed '2,${/ID/d;}'
这将删除 ID 从第 2 行开始的行。
答案2
header=$(head -n 1 input)
(printf "%s\n" "$header";
grep -vFxe "$header" input
) > output
- 将输入文件中的标题行抓取到变量中
- 打印标题
- 处理文件以
grep
省略与标题匹配的行 - 将上述两个步骤的输出捕获到输出文件中
答案3
对于那些不喜欢大括号的人
sed -e '1n' -e '/^ID/d'
n
表示pass
行号。1
d
删除所有以以下内容开头的匹配行^ID
答案4
这是一个有趣的。您可以sed
直接使用删除第一行的所有副本,并保留其他所有内容(包括第一行本身)。
sed '1{h;n;};G;/^\(.*\)\n\1$/d;s/\n.*$//' input
1{h;n;}
sed
将第一行放入保留空间,打印它,然后读入下一行 - 跳过第一行的其余命令。 (它也是跳过1
第二行的第一个测试,但这并不重要,因为该测试不会应用于第二行。)
G
将换行符后跟保留空间的内容附加到模式空间。
/^\(.*\)\n\1$/d
如果换行符之后的部分(即从保留空间附加的内容)与换行符之前的部分完全匹配,则删除模式空间的内容(从而跳到下一行)。这是重复标题的行将被删除的地方。
s/\n.*$//
删除由命令添加的文本部分G
,以便打印的只是文件中的文本行。
然而,由于正则表达式很昂贵,稍微快一点的方法是使用相同的条件(否定)并P
打印到换行符,如果换行符后面的部分(即从保留空间附加的内容)不完全匹配换行符之前的部分,然后无条件删除模式空间:
sed '1{h;n;};G;/^\(.*\)\n\1$/!P;d' input
给定输入时的输出是:
ID Data1 Data2
1 100 100
2 100 200
3 200 100
4 100 100
5 200 200