Eu tenho minhas referências como um arquivo de texto com uma longa lista de entradas e cada uma possui dois (ou mais) campos.
A primeira coluna é o URL da referência; a segunda coluna é o título que pode variar um pouco, dependendo de como a entrada foi feita. O mesmo para o terceiro campo que pode ou não estar presente.
Quero identificar, mas não remover, entradas que tenham o primeiro campo (URL de referência) idêntico. Eu sei, sort -k1,1 -u
mas isso removerá automaticamente (sem interatividade) todos, exceto o primeiro hit. Existe uma maneira de me informar para que eu possa escolher qual manter?
No extrato abaixo de três linhas que possuem o mesmo primeiro campo ( http://unix.stackexchange.com/questions/49569/
), eu gostaria de manter a linha 2 porque ela possui tags adicionais (classificar, CLI) e excluir as linhas 1 e 3:
http://unix.stackexchange.com/questions/49569/ unique-lines-based-on-the-first-field
http://unix.stackexchange.com/questions/49569/ Unique lines based on the first field sort, CLI
http://unix.stackexchange.com/questions/49569/ Unique lines based on the first field
Existe um programa para ajudar a identificar essas "duplicatas"? Então, eu posso limpar manualmente excluindo pessoalmente as linhas 1 e 3?
fonte
Respostas:
Se entendi sua pergunta, acho que você precisa de algo como:
ou:
onde
file.txt
está o seu arquivo que contém dados sobre você?Na saída, você verá o número de linhas e linhas em que o primeiro campo é encontrado duas ou mais vezes.
fonte
cut -d " " -f1 file.txt | uniq -d
me dá uma boa saída.Este é um problema clássico que pode ser resolvido com o
uniq
comandouniq
pode detectar linhas consecutivas duplicadas e remover duplicatas (-u
,--unique
) ou manter apenas duplicatas (-d
,--repeated
).Como a ordem de linhas duplicadas não é importante para você, você deve classificá-las primeiro. Em seguida, use
uniq
para imprimir apenas linhas exclusivas:Há também uma opção
-c
(--count
) que imprime o número de duplicatas para a-d
opção. Veja a página de manual deuniq
para detalhes.Se você realmente não se importa com as peças após o primeiro campo, pode usar o seguinte comando para encontrar chaves duplicadas e imprimir cada número de linha para ela (acrescente outro
| sort -n
para que a saída seja classificada por linha):Como você deseja ver linhas duplicadas (usando o primeiro campo como chave), não é possível usar diretamente
uniq
. O problema que dificulta a automação é que as partes do título variam, mas um programa não pode determinar automaticamente qual título deve ser considerado o final.Aqui está um script AWK (salve-o em
script.awk
) que usa seu arquivo de texto como entrada e imprime todas as linhas duplicadas para que você possa decidir qual excluir. (awk -f script.awk yourfile.txt
)fonte
-w
(--check-chars
) para limitar a um número fixo de caracteres, mas, vendo o seu exemplo, você tem os primeiros campos variáveis. Comouniq
não oferece suporte à seleção de campo, é necessário usar uma solução alternativa. Vou incluir um exemplo do AWK, já que é mais fácil.-w
mas o comprimento do primeiro campo é variável :(Se eu li isso corretamente, tudo que você precisa é algo como
Isso imprimirá o número da linha que contém o dupe e a própria linha. Por exemplo, usando este arquivo:
Isso produzirá esta saída:
Para imprimir apenas o número da linha, você pode fazer
E para imprimir apenas a linha:
Explicação:
O
awk
script apenas imprime o primeiro campo separado do espaço do arquivo. Use$N
para imprimir o enésimo campo.sort
classifica euniq -c
conta as ocorrências de cada linha.Isso é passado para o
while
loop, que salva o número de ocorrências como$num
e a linha como$dupe
e se$num
for maior que uma (por isso é duplicada pelo menos uma vez); ela pesquisará o arquivo para essa linha, usando-n
para imprimir o número da linha. O--
dizgrep
que o que se segue não é uma opção de linha de comando, útil para quando$dupe
começar-
.fonte
Sem dúvida, o mais detalhado da lista provavelmente poderia ser mais curto:
fornece um arquivo de texto como:
uma saída como:
Depois de escolher as linhas para remover:
fonte
Veja o seguinte classificado
file.txt
:Como a lista é curta, posso ver (depois da classificação) que existem três conjuntos de duplicatas.
Então, por exemplo, posso optar por manter:
ao invés de
Mas para uma lista mais longa, isso será difícil. Com base nas duas respostas, uma sugerindo
uniq
e a outra sugerindocut
, acho que esse comando me fornece a saída que eu gostaria:fonte
cut
. Se você estiver executando um trabalho de desduplicação, os números de linha podem ser muito úteis. Para imprimir todas as duplicatas, use a-D
opção em vez de-d
.for dup in $(cut -d " " -f1 file.txt | uniq -d); do grep -n $dup file.txt; done
como na minha resposta. Ele fornecerá uma visualização melhor sobre o que você está interessado.É assim que eu resolvi:
file_with_duplicates:
Arquivo classificado e deduplicado pelas colunas 1 e 2:
Arquivo classificado apenas pelas colunas 1 e 2:
Mostre apenas a diferença:
fonte