uniq mostrando linhas duplicadas

2
$ grep home american.txt | sort | uniq                                                                                            
A home and a country should leave us no more!                                                                                        
Between their loved home and the war's desolation!                                                                                 
O'er the land of the free and the home of the brave!                                                                                  
O'er the land of the free and the home of the brave!                                                                                  
O'er the land of the free and the home of the brave?     

Por que isso mostra duas linhas duplicadas?

Aqui está a saída de grep home american.txt | cat -A :

O'er the land of the free and the home of the brave?^M$
O'er the land of the free and the home of the brave!^M$
A home and a country should leave us no more! ^M$
O'er the land of the free and the home of the brave!^M$
Between their loved home and the war's desolation!^M$
O'er the land of the free and the home of the brave!$
    
por WinMacLinUser 09.10.2015 / 05:45

3 respostas

0

O'er the land of the free and the home of the brave!

Existem 3 ocorrências da linha acima. As duas primeiras ocorrências têm um retorno de carro no final. A terceira ocorrência não. você pode usar o seguinte comando para visualizá-lo:

cat -A american.txt

É causado pelo fato de esse arquivo de texto não ter uma linha vazia no final.
Eu acho que é uma convenção no mundo Unix / Linux sempre ter uma linha vazia no final dos arquivos de texto.

Algumas outras coisas que achei interessantes estavam sendo testadas:

  • o comando funciona de maneira diferente no cygwin.
  • grep home american.txt | sort| uniq -u funciona muito bem.
por 09.10.2015 / 06:37
2

Como suspeito por David Dai e cas as duas linhas são de fato diferentes, mas a única diferença é em caracteres invisíveis.

Seu arquivo é um arquivo de texto do Windows. Nos arquivos de texto do Windows, as linhas são separadas pela seqüência de dois caracteres CR, LF (retorno de carro, alimentação de linha). Em um arquivo de texto Unix, as linhas são finalizadas por um caractere LF (feed de linha, também conhecido como nova linha). cat -A mostra um CR como ^M e um feed de linha como $ seguido por uma quebra de linha.

Quando um arquivo de texto do Windows é processado por um utilitário Unix, o utilitário Unix vê um caractere CR extra no final de cada linha. No que diz respeito aos utilitários Unix, o CR é apenas um caractere comum; uma linha com um CR no final é diferente de uma linha idêntica, exceto pela falta de um CR no final. Além disso, no Windows, a seqüência de nova linha é um separador, portanto, não há CR, LF no final do arquivo. Mas no Unix, um arquivo de texto sempre termina com um caractere LF, a menos que esteja vazio. Então, quando você processa um arquivo de texto do Windows com um utilitário Unix, o que o utilitário Unix vê é um arquivo com CR no final de cada linha (porque os caracteres CR não fazem parte da codificação Unix de uma nova linha) e algum texto à direita isso não faz parte de uma linha (por causa da falta de uma nova linha no final).

Utilitários de texto Unix diferem no que eles fazem quando sua entrada não é um arquivo de texto válido devido à falta de uma nova linha final. Os utilitários GNU - que é o que você encontrará no Linux não integrado e no Cygwin - se esforçam para tratar esses arquivos como arquivos de texto e preservam a falta de uma nova linha final. O comando sort embaralha as linhas e, embora processe uma linha de entrada inacabada, sempre emite uma nova linha no final da saída. Assim, para o comando sort , o que você tem parece um monte de linhas, cada uma delas termina com o caractere CR, exceto a última linha de entrada que não termina com CR. Na saída, todas as linhas terminam com CR, exceto aquela linha que corresponde à última linha de entrada.

uniq vê um monte de linhas que terminam com brave! e um CR e retém apenas uma delas. Ele também vê uma linha que termina com brave! , mas sem CR, que ela emite obedientemente, pois essa linha difere de todas as outras linhas.

Quando você imprime a saída no terminal, um caractere CR instrui o terminal a mover o cursor para o início da linha atual; um caractere LF instrui o terminal a mover o cursor para o início da próxima linha. Assim, as sequências LF e CR, LF não são visualmente distinguíveis, e você vê duas linhas idênticas. O comando cat -A adiciona caracteres imprimíveis para torná-los distintos.

    
por 10.10.2015 / 02:45
1

Uma dessas linhas que terminam em brave! tem um retorno de carro ( ^M ), a outra não. uniq está certo, eles são diferentes.

Todas as linhas no arquivo, exceto a última, têm retornos de carro. Tem-los porque foi criado por um editor de texto MS-DOS ou Windows (que usa CR / LF para fins de linha em vez de unixish LF-only ou \ n). A última linha no arquivo não tem CR ou LF (caso contrário, haverá uma linha em branco abaixo dela).

É por isso que, por exemplo, se você tail -1 american.txt obtiver o próximo prompt do shell na mesma linha do texto, sem uma quebra de linha de alimentação.

    
por 09.10.2015 / 06:49