bash:删除具有相同开头的行

时间:2016-08-11 12:46:00

标签: bash sed

有一个包含

等内容的文件
2016-03-24 22:10:05,399 INFO aa
2016-03-24 22:10:05,399 INFO bb
2016-03-24 22:10:06,903 INFO cc
2016-03-24 22:10:07,804 INFO dd
2016-03-24 22:10:07,904 INFO ee
2016-03-24 22:10:05,399 INFO ff
2016-03-24 22:10:05,399 INFO gg

我想删除具有相同开头的行(INFO blab-bla-bla...之前的部分)。 我可以使用像Ruby这样的全功能编程语言来执行它,但由于文件大小和其他一些原因我想使用sed

预期结果:

2016-03-24 22:10:05,399 INFO aa
2016-03-24 22:10:06,903 INFO cc
2016-03-24 22:10:07,804 INFO dd
2016-03-24 22:10:07,904 INFO ee
2016-03-24 22:10:05,399 INFO ff

过去为了删除相同的行,我使用了命令

  

sed'$!N; /^(.*)\n\1$/!P; d'

如果我理解正确的话,读取输入行,然后将下一行的\ n(如果它不是最后一行)附加到模式空间,然后,如果有一个序列,如“从开头到\的任何行” n加上相同的行直到行结束“,打印第二行并删除它。

我试图使用上面提到的一个更复杂的sed命令但没有成功,至少剩下一个逻辑块:

cat temp.log | sed '$!N; s/ INFO.*//; /^\(.*\)\n\1$/!P; D'

我想要做的是从当前行中删除以INFO开头的所有内容,然后附加下一行,

2016-03-24 22:10:05,399
2016-03-24 22:10:05,399 INFO bb

删除以INFO开头的所有内容,

2016-03-24 22:10:05,399
2016-03-24 22:10:05,399

然后删除第二行,如果它们相同的话。如何替换下一行?我使用\1&尝试了几项但没有效果。

5 个答案:

答案 0 :(得分:2)

根据我对您的问题的理解,这是另一个可能的awk脚本:

awk -F"[, ]" 'prev!=$3; {prev=$3}' file

它将基于与前一行具有相同值的第3个元素去除所有行。

答案 1 :(得分:1)

命令:

awk -F" INFO " 'seen[$1]==0{print; seen[$1]++;next}  seen[$1]==1{seen[$1]=0}' sample.csv

使用"信息"作为字段分隔符并将第一个字段存储到数组seen中,第一个字段是INFO之前的日期时间。如果日期时间不在数组中,则看到[$ 1]返回false,!将使其成立。 ++是递增运算符,它会增加发生时间

如果看到连续的重复日期时间,

seen[$1]==1{seen[$1]=0}将值重置为0

答案 2 :(得分:1)

这是uniq的工作。通过仅比较前23个字符(日期和时间),以下简单行将完全符合您的要求:

$ uniq -w 23 temp.log

答案 3 :(得分:1)

这是一个非正统的解决方案......

$ rev file | uniq -f2 | rev

2016-03-24 22:10:05,399 INFO aa
2016-03-24 22:10:06,903 INFO cc
2016-03-24 22:10:07,804 INFO dd
2016-03-24 22:10:07,904 INFO ee
2016-03-24 22:10:05,399 INFO ff

答案 4 :(得分:1)

sed用于单个行上的简单替换,即全部。如果你使用s,g和p以外的sed命令(和-n)那么你使用了错误的工具,因为所有其他的sed结构在1970年代中期发明awk时已经过时了。

$ awk '{c=$1$2} p!=c; {p=c}' file
2016-03-24 22:10:05,399 INFO aa
2016-03-24 22:10:06,903 INFO cc
2016-03-24 22:10:07,804 INFO dd
2016-03-24 22:10:07,904 INFO ee
2016-03-24 22:10:05,399 INFO ff