如何删除具有相同中间块的行?

时间:2014-10-05 16:00:22

标签: shell replace awk sed

对于命令行忍者来说,这可能是一个简单的问题,但我无法弄清楚我的生活。截至目前,我正在使用PHP脚本来完成此任务,但我需要使用awk / sed / cut或类似方法来完成。

我有一个这样的日志文件:

123 | foo | 12.13
756 | bar | 14.25
236 | baz | 11.23
536 | foo  | 10.13
947 | bar | 34.25
134 | baz | 11.26

我需要删除所有具有相同中间元素的行。如果 重复,则需要保留较新版本。删除后文件的输出应如下所示:

536 | foo  | 10.13
947 | bar | 34.25
134 | baz | 11.26

我是新手,并且不知道如何做到这一点,所以在正确的方向上稍微推动会有很大的帮助。

4 个答案:

答案 0 :(得分:1)

您可以使用自定义字段分隔符使用此awk命令:

awk -F' *\\| *' '!data[$2]{a[++k]=$2} {data[$2]=$0} 
           END{for (i=1; i<=k; i++) print data[a[i]]}' file
536 | foo  | 10.13
947 | bar | 34.25
134 | baz | 11.26

答案 1 :(得分:1)

如果您不关心输出顺序

perl -F'\s*\|\s*' -lanE '$s{$F[1]}=$_}{say $s{$_} for keys %s' <ca.txt

打印

134 | baz | 11.26
947 | bar | 34.25
536 | foo  | 10.13

答案 2 :(得分:1)

$ tac file | awk -F' +[|] +' '!seen[$2]++' | tac
536 | foo  | 10.13
947 | bar | 34.25
134 | baz | 11.26

或者如果您更喜欢仅使用awk的解决方案:

$ awk -F' +[|] +' 'NR==FNR{fnr[$2]=FNR; next} FNR==fnr[$2]' file file
536 | foo  | 10.13
947 | bar | 34.25
134 | baz | 11.26

答案 3 :(得分:0)

sed -e ":a
$ !{N;ba
   }
:b
s/[0-9]* | \([^ ]*\) | [0-9.]*\n\(.*\)\1/\2\1/g
t b" YourFile

sed posix版本(所以--posix用于GNU sed,特别是由于在|内使用了s///