Exclua as linhas que contêm as mesmas informações, mas em ordem diferente

4

Digamos que eu tenha duas linhas (em um arquivo txt)

Monday, Tuesday, Week
Tuesday, Monday, Week

Eles contêm as mesmas informações, mas as informações (a primeira e a segunda colunas) estão em uma ordem diferente em cada linha, portanto, não posso simplesmente usar sort ou uniq para me livrar delas.

Como posso excluir todas as linhas duplicadas, que contêm as mesmas informações?

    
por sadboy 24.11.2016 / 04:29

3 respostas

5

com perl :

perl -lne 'print unless $seen{join ",", sort split /,\h*/}++'
    
por 24.11.2016 / 13:41
1

Se você não se importa se você preserva um pedido dentro da linha vista dentro do arquivo, você colocaria cada linha em um formato padrão (ou canônico), e então usaria sort / uniq ou similar.

Desde que você adicionou que você se preocupa em preservar uma das ordens representadas no arquivo, a abordagem que eu tomaria seria classificar cada linha em ordem canônica, e produzir isso junto com a linha original, então classificar em essa primeira representação canonicalizada como uma chave e descartar linhas com chaves duplicadas e, em seguida, cortar a chave.

Esta é a primeira parte. Ele preenche cada linha original com uma representação canonicalizada do conteúdo da linha:

( while read f; do  echo $f | tr -d "," | tr " " "\n" | sort | tr "\n" " " ; echo ':' $f ; done  < data ) | awk -F":" '!_[$1]++' | cut -f2 -d: |cut -c2-

Você pode executar partes disso para ver o que ele faz. A primeira parte emite os registros originais com uma representação canonicalizada (lexicamente ordenada) com um delimitador:

 $ cat data
Monday, Tuesday, Week
Tuesday, Monday, Week
Tuesday, Thursday, Week
Week, Thursday, Tuesday

 $ ( while read f; do  echo $f | tr -d "," | tr " " "\n" | sort | tr "\n" " " ; echo ':' $f ; done  < data )
Monday Tuesday Week : Monday, Tuesday, Week
Monday Tuesday Week : Tuesday, Monday, Week
Thursday Tuesday Week : Tuesday, Thursday, Week
Thursday Tuesday Week : Week, Thursday, Tuesday

Então eu uso o awk para construir um hash com uma contagem de cada vez que uma chave foi vista, com uma impressão implícita para a primeira instância de cada, devido ao não com '!'

 $ ( while read f; do  echo $f | tr -d "," | tr " " "\n" | sort | tr "\n" " " ; echo ':' $f ; done  < data ) | awk -F":" '!_[$1]++' | cut -f2 -d: |cut -c2-
Monday, Tuesday, Week
Tuesday, Thursday, Week
    
por 24.11.2016 / 04:43
1

Solução complicada (isso é apenas uma amostra) - funciona bem no meu bash. Todas as linhas / palavras podem ser divididas em caracteres e, em seguida, esses caracteres podem ser classificados. Se a linha ordenada 1 = linha ordenada 2, então você tem a duplicata.

word1+=( $(echo "this is my life" |fold -w1) )
sortedword1=($(echo ${word1[@]} | tr " " "\n" | sort))
word2+=( $(echo "is this my life" |fold -w1) )
sortedword2=($(echo ${word1[@]} | tr " " "\n" | sort))
echo "${sortedword1[@]}"
echo "${sortedword2[@]}"

if [[ $sortedword1 == $sortedword2 ]]; then
echo "Word 1 and Word 2 are the same, delete one of them"
fi

Saída:

e f h i i i l m s s t y
e f h i i i l m s s t y
Word 1 and Word 2 are the same, delete one of them
    
por 24.11.2016 / 14:21