如何只获得唯一的结果而不需要对数据进行排序?

如何只获得唯一的结果而不需要对数据进行排序?
$ cat data.txt 
aaaaaa
aaaaaa
cccccc
aaaaaa
aaaaaa
bbbbbb
$ cat data.txt | uniq
aaaaaa
cccccc
aaaaaa
bbbbbb
$ cat data.txt | sort | uniq
aaaaaa
bbbbbb
cccccc
$

我需要的结果是显示原始文件中的所有行,删除所有重复项(不仅仅是连续的行),同时保持文件中语句的原始顺序

在这个例子中,我实际寻找的结果是

aaaaaa
cccccc
bbbbbb

一般情况下我该如何执行这种通用uniq操作?

答案1

perl -ne 'print unless $seen{$_}++' data.txt

或者,如果您必须有一个无用的使用cat:

cat data.txt | perl -ne 'print unless $seen{$_}++'

以下是awk针对缺少 Perl 的系统的翻译:

awk '!seen[$0]++' data.txt
cat data.txt | awk '!seen[$0]++'

答案2

约翰有一个工具叫做unique

usr@srv % cat data.txt | unique out
usr@srv % cat out
aaaaaa
cccccc
bbbbbb

要在单个命令行中不使用其他工具来实现相同的目标有点复杂:

usr@srv % cat data.txt | nl | sort -k 2 | uniq -f 1 | sort -n | sed 's/\s*[0-9]\+\s\+//'
aaaaaa
cccccc
bbbbbb

nl在行前面打印行号,因此如果我们sort/uniq在行后面,我们可以恢复行的原始顺序。sed之后只需删除行号;)

答案3

我更喜欢用这个:

cat -n data.txt | sort --key=2.1 -b -u | sort -n | cut -c8-

cat -n添加行号,

sort --key=2.1 -b -u对第二个字段(添加的行号之后)进行排序,忽略前导空格,保留唯一的行

sort -n按严格的数字顺序排序

cut -c8-保留从第 8 列到 EOL 的所有字符(即省略我们包含的行号)

答案4

使用(以前称为 Perl_6)

~$ raku -e '.put for lines.unique;'  file

或者更多awk-类似语法):

~$ raku -ne 'state %h; .put unless %h{$_}++ ;'  file

输入示例:

aaaaaa
aaaaaa
cccccc
aaaaaa
aaaaaa
bbbbbb

示例输出:

aaaaaa
cccccc
bbbbbb

https://docs.raku.org
https://raku.org

相关内容