Como o uniq não é único o suficiente para que também haja uniq --unique?

35

Aqui estão os comandos em um arquivo aleatório de pastebin :

wget -qO - http://pastebin.com/0cSPs9LR | wc -l
350
wget -qO - http://pastebin.com/0cSPs9LR | sort -u | wc -l
287
wget -qO - http://pastebin.com/0cSPs9LR | sort | uniq | wc -l
287
wget -qO - http://pastebin.com/0cSPs9LR | sort | uniq -u | wc -l
258

As páginas man não são claras sobre o que o -u flag está fazendo. Algum conselho?

    
por enfascination 18.06.2015 / 12:20

4 respostas

39

Versão resumida:

  • uniq , sem -u , torna cada linha da saída única.
  • uniq -u imprime apenas todas as linhas exclusivas da entrada .

Versão ligeiramente mais longa:

uniq é para lidar com arquivos que possuem linhas duplicadas e somente quando essas linhas aparecem sucessivamente na entrada. Assim, para seus propósitos, uma linha exclusiva é aquela que não é duplicada imediatamente.

( uniq tem uma memória de curto prazo muito limitada; nunca se lembrará se uma linha apareceu anteriormente na entrada, a menos que fosse a linha imediatamente anterior - é por isso que uniq é frequentemente associado a sort .)

Quando encontra uma linha de linhas duplicadas, uniq , sem o -u arg, imprime uma cópia uma dessa linha. (Faz cada linha da saída única ).

Com o argumento -u , ele imprime cópias zero dessa linha - execuções de duplicatas são omitidas da saída.

    
por 18.06.2015 / 13:47
52

uniq com -u ignora todas as linhas que tiverem duplicatas. Assim:

$ printf "%s\n" 1 1 2 3 | uniq
1
2
3
$ printf "%s\n" 1 1 2 3 | uniq -u
2
3

Geralmente, uniq imprime linhas no máximo uma vez (assumindo entrada classificada). Esta opção, na verdade, imprime linhas que são verdadeiramente exclusivas (não tendo aparecido novamente).

    
por 18.06.2015 / 12:26
18

especificação uniq POSIX descreveu claramente:

-u
    Suppress the writing of lines that are repeated in the input.

-u option faz uniq não imprimir linhas repetidas.

A maioria das implementações de uniq usou a comparação de bytes, enquanto o% GNUuniq usou a ordem de agrupamento para filtrar linhas duplicadas. Por isso, pode produzir resultados errados em algumas localidades, exemplo em en_US.UTF-8 locale:

$ printf '%b\n' '\U2460' '\U2461' | uniq
①

e -u não forneceram linhas:

$ printf '%b\n' '\U2460' '\U2461' | uniq -u
<blank>

Portanto, você deve definir a localidade como C para obter uma comparação de bytes:

$ printf '%b\n' '\U2460' '\U2461' | LC_ALL=C uniq
①
②
    
por 18.06.2015 / 12:33
8

normal:

echo "a b a b c c c" | tr ' ' '\n'
a
b
a
b
c
c
c

uniq: não há duas linhas repetitivas subsequentes

echo "a b a b c c c" | tr ' ' '\n' | uniq
a
b
a
b
c

classificado

echo "a b a b c c c" | tr ' ' '\n' | sort
a
a
b
b
c
c
c

sort -u: não há duas linhas repetitivas

echo "a b a b c c c" | tr ' ' '\n' | sort -u
a
b
c

sort / uniq: todos distintos

echo "a b a b c c c" | tr ' ' '\n' | sort | uniq
a
b
c

conta ocorrências distintas

echo "a b a b c c c" | tr ' ' '\n' | sort | uniq -c
2 a
2 b
3 c

apenas linhas que não são repetidas (não classificadas primeiro)

echo "a b a b c c c" | tr ' ' '\n' | uniq -u
a
b
a
b

apenas linhas que não são repetidas (após a classificação)

echo "a b a b c c c Z" | tr ' ' '\n' | sort | uniq -u
Z

uniq -d: imprima apenas linhas duplicadas, uma para cada grupo

echo "a b a b c c c" | tr ' ' '\n' | uniq -d
c

.. contado

echo "a b a b c c c" | tr ' ' '\n' | uniq -dc
3 c
    
por 19.06.2015 / 01:02

Tags