Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash 删除文本文件中每行有一个单词更改的重复行_Bash_Shell_Awk - Fatal编程技术网

Bash 删除文本文件中每行有一个单词更改的重复行

Bash 删除文本文件中每行有一个单词更改的重复行,bash,shell,awk,Bash,Shell,Awk,我想删除生产线并拥有最终产品: somethingsame,somethingsame_usage,2015-11-30 01:00:00,0 somethingsame,somethingsame_usage,2015-11-30 02:00:00,0 somethingsame,somethingsame_usage,2015-11-30 03:00:00,0 somethingelse,somethingelse_usage,2015-11-30 01:00:00,0 somethinge

我想删除生产线并拥有最终产品:

somethingsame,somethingsame_usage,2015-11-30 01:00:00,0
somethingsame,somethingsame_usage,2015-11-30 02:00:00,0
somethingsame,somethingsame_usage,2015-11-30 03:00:00,0
somethingelse,somethingelse_usage,2015-11-30 01:00:00,0
somethingelse,somethingelse_usage,2015-11-30 02:00:00,0
somethingelse,somethingelse_usage,2015-11-30 03:00:00,0

唯一改变的是不同的时间(每个数据,即相同的东西与相同的东西),但其他一切都是相同的。无论我选择哪一行/时间;我只想要一个。

以下解决方案使用了
awk
,但它不是我最喜欢的(将在单独的答案中写入)

它是干什么的

逐行跟踪上一行的相关值(前两个字段,存储在变量
previous1
previous2
中)。这些值在处理行结束时更新

找到当前值(
current1
current2
)与前面的值不同的行后,只需调用
print$0
即可打印整行

我还将字段分隔符(
FS
value)配置为逗号

您可以建立更详细的标准来决定两行是否相等,以及新行是否需要打印

以下是完整的控制台转储:

somethingsame,somethingsame_usage,2015-11-30 02:00:00,0
somethingelse,somethingelse_usage,2015-11-30 03:00:00,0

如果您不关心行的输出顺序,可以使用
-u
(unique)命令行标志,使用
-u
(unique)命令行标志进行排序,该标志只包含一组唯一行的一个实例

uniq
不同,
sort-u
只比较由
-k
选项定义的行的一部分,因此您可以精确地指定哪些字段将被计算为唯一性测试的一部分。因此,在这种情况下,您可以使用:

$ cat input.txt 
somethingsame,somethingsame_usage,2015-11-30 01:00:00,0
somethingsame,somethingsame_usage,2015-11-30 02:00:00,0
somethingsame,somethingsame_usage,2015-11-30 03:00:00,0
somethingelse,somethingelse_usage,2015-11-30 01:00:00,0
somethingelse,somethingelse_usage,2015-11-30 02:00:00,0
somethingelse,somethingelse_usage,2015-11-30 03:00:00,0
$ awk 'BEGIN { FS="," } { current1 = $1; current2 = $2; if ((previous1 != current1) && (previous2 != current2)) { print $0 } previous1 = current1; previous2 = current2; }' input.txt
somethingsame,somethingsame_usage,2015-11-30 01:00:00,0
somethingelse,somethingelse_usage,2015-11-30 01:00:00,0
$ 
其中
-t,
表示字段分隔符是逗号,
-k1,2
表示“键”由从第一个字段的第一个字符到第二个字段的最后一个字符的所有内容组成


请注意,
-k
参数是一个范围,而不是一个列表:
-k1,3
表示前三个字段,而
-k2
表示“从第二个字段到行的末尾”。

这是一种不同的解决方案,因为输入文件已经排序

请注意,问题在于,我只是剥离了行中不相关的部分,因此它不会出现在结果中:

sort -u -t, -k1,2

惯用的
awk
解决方案如下

$ cat input.txt
somethingsame,somethingsame_usage,2015-11-30 01:00:00,0
somethingsame,somethingsame_usage,2015-11-30 02:00:00,0
somethingsame,somethingsame_usage,2015-11-30 03:00:00,0
somethingelse,somethingelse_usage,2015-11-30 01:00:00,0
somethingelse,somethingelse_usage,2015-11-30 02:00:00,0
somethingelse,somethingelse_usage,2015-11-30 03:00:00,0
$ cat input.txt | awk 'BEGIN { FS = "," } { print $1 "," $2 }' | uniq
somethingsame,somethingsame_usage
somethingelse,somethingelse_usage
$ 

选择第一个实例。

欢迎使用SO。如果您向我们展示了迄今为止您尝试过的代码,您的帖子可能会有所改进。Minahil,如果您的输入文件没有排序,这是一个非常好的解决方案。如果您的输入已排序,则再次对其调用sort可能是多余的,并且在处理时间方面代价高昂。这取决于输入的大小。@RamónGilMoreno:sort实用程序对已经排序的大文件进行了很好的优化。我以前读过这个问题,我不怀疑sort会处理大文件,但看起来仍然需要消耗大量资源。IMHO.my input未排序,我正在处理大约500000行,另一种解决方案是什么,这似乎有效。@Minahil:如果您的输入未排序,并且您希望删除重复项,即使它们不是连续的,这就是解决方案。
$ awk -F, '!a[$1]++' log

somethingsame,somethingsame_usage,2015-11-30 01:00:00,0
somethingelse,somethingelse_usage,2015-11-30 01:00:00,0