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

bash:删除具有相同开头的行,bash,sed,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 我想删除具有相同开头的行(信

有一个文件的内容如下

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
我想删除具有相同开头的行(信息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$/!PD'

如果我理解正确,它将读取输入行,然后在模式空间中添加下一行(如果不是最后一行),然后,如果存在类似“从开始到\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
&
尝试了几件事,但没有效果。

命令:

awk -F" INFO " 'seen[$1]==0{print; seen[$1]++;next}  seen[$1]==1{seen[$1]=0}' sample.csv
使用“INFO”作为字段分隔符,并将第一个字段存储到数组中,如图所示,第一个字段是INFO之前的日期时间。如果datetime不在数组中,seen[$1]返回false和
将使其成为现实<代码>++
是增量运算符,它增加了发生时间


seen[$1]==1{seen[$1]=0}
如果看到连续重复的日期时间,请将值重置为0

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

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

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

这是uniq的作业。下面的简单行只比较前23个字符(日期和时间),完全符合您的要求:


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

$ 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

sed是对单个行的简单替换,仅此而已。如果您使用的sed命令不是s、g和p(带-n),那么您使用的工具是错误的,因为在20世纪70年代中期发明awk时,所有其他sed构造都已过时

$ 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


您的
ff
gg
行与
aa
bb
ff
具有相同的日期时间,
gg
行不应该出现为什么
,399
在预期结果中出现两次?@hek2mgl因为在这种情况下,只检查下一行就足够了,而不是全部。@non random\u passer,在您的一条注释中,您声明输入是按时间戳排序的,但OP仍然显示其他内容(第一行和最后两行都是相同的时间戳-aa、bb、ff和gg)。哪一行?缺少最后一行输出。似乎此变体删除了文件中的所有其他重复项,而不仅仅是下一行,对吗?我还注意到,在测试时,我在编辑的文件的末尾得到了一个空行,但它完全正常。@nonrandom\u passer这与预期的输出不匹配。如果你改变了主意,请编辑你原来的帖子,并将记录整理好。编辑以达到预期的结果。请看我对原问题的评论。我的第一个答案是基于描述的。谢谢大家:)@nonrandom\u passer,但您发布的示例输入不是按时间戳排序的。在发布示例输入/输出时,重要的是它能很好地反映您的真实数据,否则您会得到一些您没有遇到的问题的答案。谢谢,在总是有固定数量的字符的情况下很好。实际上,只要时间戳格式保持不变,这对任何数量的字符都有效。谢谢,很好。分隔符只能是一个空格?在其man中未找到更改分隔符的选项。是的,uniq仅将空格识别为分隔符。这里的另一个问题是,与sed/awk相比,此变体如何处理大文件。只要日期/时间信息后始终有两个字段(INFO和xx),此选项就可以工作。如果在日期/时间之后可以有数量可变的(空格分隔的)字段,则它无法正常工作。这意味着它是当前数据集的解决方案,但不一定是更一般的数据集。是的,这不是一般的解决方案,取决于信息后面正好有一个字段。
$ 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