给定一个如此排序的文件:
AAA 1 2 3
AAA 2 3 4
AAA 3 4 2
BBB 1 1 1
BBB 1 2 1
和
的期望输出AAA 1 2 3
BBB 1 1 1
使用sed实现这一目标的最佳方法是什么?
基本上,如果col以与上一行相同的字段开头,我该如何删除它?其余数据必须保留在输出中。
我想必须有一些方法可以使用保持缓冲区,分支或测试命令来执行此操作。
答案 0 :(得分:1)
这可以用AWK完成:
$ gawk '{if (last != $1) print; last = $1}' in.txt
AAA 1 2 3
BBB 1 1 1
答案 1 :(得分:1)
使用awk的另一种方式:
awk '!($1 in a){print;a[$1]}' file
答案 2 :(得分:0)
也许sed
有一种更简单的方式,但是:
sed ':a;N;/\([[:alnum:]]*[[:space:]]\).*\n\1/{s/\n.*//;ta};P;D'
这会产生输出
AAA 1 2 3
BBB 1 1 1
与问题中的不同,但与描述匹配:
如果col以与上一行相同的字段开头,我该如何删除它?
答案 3 :(得分:0)
这可能适合你(GNU sed):
sed -r ':a;$!N;s/^((\S+\s).*)\n\2.*/\1/;ta;P;D' file
或者只是:
sort -uk1,1 file
答案 4 :(得分:0)
使用GNU awk
的一种方式:
awk '!array[$1]++' file.txt
结果:
AAA 1 2 3
BBB 1 1 1
答案 5 :(得分:0)
使用sed:
#!/bin/sed -nf
P
: loop
s/\s.*//
N
/\([^\n][^\n]*\)\n\1/ b loop
D
首先,我们必须将-n
标记传递给sed,这样它才能打印我们告诉它的内容。
我们首先使用“P”命令打印该行,因为第一行将始终打印,我们将强制sed仅在我们需要时执行此行。
现在我们要做一个循环。我们通过“:”命令定义一个带有起始标签的循环(在这种情况下,我们将标签命名为“loop”),并在必要时使用“b”命令(或“t”测试)跳回到此标签命令)。这个循环非常简单:
\(
开头,以\)
结尾)。在这种情况下,我们匹配所有不是换行符的字符(即。[^\n]
)直到行的末尾。我们通过匹配至少一个非换行符后跟任意序列来完成此操作。这可以防止在换行符之前匹配空字符串。捕获后,我们使用特殊变量\1
匹配换行符后跟捕获结果,其中包含与第一次捕获匹配的输入。如果成功,我们有一行重复第一个字段,所以我们用“b”分支命令跳回到循环的开头。这可以缩短为一行(注意我们已将“loop”标签重命名为“a”):
sed -e 'P;:a;s/\s.*//;N;/\([^\n][^\n]*\)\n\1/ba;D'