抱歉,我必须编辑我的示例,因为我没有正确表达我的查询。假设我有 .txt 文件:
Happy sad
Happy sad
Happy sad
Sad happy
Happy sad
Happy sad
Mad sad
Mad happy
Mad happy
我想删除任何唯一的字符串。留下文件:
Happy sad
Happy sad
Happy sad
Happy sad
Happy sad
Mad happy
Mad happy
我知道 sort 能够消除重复项 ( sort file.txt | uniq
),那么我们是否可以使用命令在 bash 中执行相反的操作?或者我只需要找出一个 while 循环?顺便说一句uniq -D file.txt > output.txt
,不起作用。
答案1
使用awk
:
$ awk 'seen[$0]++; seen[$0] == 2' file
Happy sad
Happy sad
Happy sad
Happy sad
Happy sad
Mad happy
Mad happy
这使用每行的文本作为关联数组的键seen
。第一个seen[$0]++
将导致打印之前已经见过的行,因为与该行关联的值在第二次及随后的时间看到该行时将不为零。seen[$0] == 2
如果这是第二次看到该行,则会再次打印该行(否则,您将错过每个重复行的一次出现)。
这与 awk '!seen[$0]++'
有时用于消除重复而不排序(参见例如awk '!a[$0]++' 是如何工作的?)。
仅获取重复行的一份副本:
awk 'seen[$0]++ == 1' file
或者,
sort file | uniq -d
答案2
如果重复项可能不连续并且您需要保留输入中的顺序,则可以使用awk
两遍来完成此操作,一次用于计算出现次数,另一次用于打印在中出现多次的行第一遍:
awk 'second_pass {if (c[$0] > 1) print; next}
{c[$0]++}' file.txt second_pass=1 file.txt
答案3
从man uniq
:
-D 打印所有重复行
您可以像这样实现您的目标:
uniq -D file.txt
答案4
这可能是仅限 Linux 的解决方案,因为它使用uniq
's-u
选项。如果您正在运行其他版本,您可以通过使用uniq -c
then 过滤等来解决这个问题。^ *1
sort < in | uniq --unique | grep --invert-match --line-regexp --fixed-strings --file - in
前2阶段将推出
Mad sad
Sad happy
下一阶段将删除与这些行完全匹配的行。为了清晰起见,我选择了较长的选项;我自己很少使用它们简短的形式是sort < in | uniq -u | grep -v -x -F -f - in