Eu tenho um arquivo .csv como este:
stack2@example.com,2009-11-27 01:05:47.893000000,example.net,127.0.0.1
overflow@example.com,2009-11-27 00:58:29.793000000,example.net,255.255.255.0
overflow@example.com,2009-11-27 00:58:29.646465785,example.net,256.255.255.0
...
Eu tenho que remover e-mails duplicados (a linha inteira) do arquivo (ou seja, uma das linhas que contém [email protected]
o exemplo acima). Como uso uniq
apenas no campo 1 (separado por vírgulas)? Segundo man
, uniq
não tem opções para colunas.
Eu tentei algo com sort | uniq
mas não funciona.
man sort
). Representa a posição inicial e final.sort
's manpage diz: ' com , cheque de ordenação estrita, sem , saída apenas o primeiro de um igual prazo .' Portanto, é de fato "a primeira ocorrência da duplicata antes da classificação".-u
--unique
-c
-c
-F
define o separador de campos.$1
é o primeiro campo._[val]
procuraval
no hash_
(uma variável regular).++
incrementar e retornar valor antigo.!
retorna não lógico.fonte
awk -F',' '{ x[$1]=$0 } END { for (i in x) print x[i] }' file
!_[$1][$2]++
pode ser usado para classificar pelos dois primeiros campos. Meuawk
-fu não é forte o suficiente para ser capaz de ser único em vários campos. :(Para considerar várias colunas.
Classifique e forneça uma lista exclusiva com base nas colunas 1 e 3:
-t :
dois pontos é separador-k 1,1 -k 3,3
com base nas colunas 1 e 3fonte
ou se você quiser usar o uniq:
<mycvs.cvs tr -s ',' ' ' | awk '{print $3" "$2" "$1}' | uniq -c -f2
dá:
fonte
cat
! Em vez de canalizar para tr, deixe tr ler o arquivo usando<
. A tubulaçãocat
é uma complicação desnecessária comum usada por iniciantes. Para grandes quantidades de dados, há um efeito no desempenho.rev
.Se você quiser reter a última duplicata, poderá usar
Qual foi a minha exigência
aqui
tac
irá reverter o arquivo linha por linhafonte
Aqui está uma maneira muito bacana.
Primeiro formate o conteúdo de modo que a coluna a ser comparada para exclusividade tenha uma largura fixa. Uma maneira de fazer isso é usar o awk printf com um especificador de largura de campo / coluna ("% 15s").
Agora, as opções -f e -w do uniq podem ser usadas para pular os campos / colunas anteriores e especificar a largura de comparação (largura da (s) coluna (s)).
Aqui estão três exemplos.
No primeiro exemplo ...
1) Transforme temporariamente a coluna de interesse em uma largura fixa maior ou igual à largura máxima do campo.
2) Use a opção -f uniq para ignorar as colunas anteriores e use a opção -w uniq para limitar a largura ao tmp_fixed_width.
3) Remova os espaços finais da coluna para "restaurar" sua largura (assumindo que não havia espaços finais anteriormente).
No segundo exemplo ...
Crie uma nova coluna uniq 1. Em seguida, remova-a após a aplicação do filtro uniq.
O terceiro exemplo é o mesmo que o segundo, mas para várias colunas.
fonte
bem, mais simples do que isolar a coluna com o awk, se você precisar remover tudo com um certo valor para um determinado arquivo, por que não fazer grep -v:
por exemplo, para excluir tudo com o valor "col2" na segunda linha: col1, col2, col3, col4
Se isso não for bom o suficiente, porque algumas linhas podem ser removidas incorretamente, possivelmente com o valor correspondente sendo exibido em uma coluna diferente, você pode fazer algo assim:
awk para isolar a coluna incorreta: por exemplo
o -F define o campo delimitado como ",", $ 2 significa coluna 2, seguida por algum delimitador personalizado e, em seguida, a linha inteira. Você pode filtrar removendo as linhas que começam com o valor incorreto:
e depois retire o material antes do delimitador:
(note: o comando sed é desleixado porque não inclui valores de escape. Além disso, o padrão sed deve realmente ser algo como "[^ |] +" (ou seja, qualquer coisa que não seja o delimitador). Mas esperamos que isso esteja claro o suficiente.
fonte
Classificando o arquivo
sort
primeiro, você pode aplicaruniq
.Parece classificar o arquivo muito bem:
Você também pode fazer alguma mágica do AWK:
fonte
sort
, portantouniq
,sort
precisa ser feito antes de fazer,uniq
caso contrário, não funciona (mas você pode pular o segundo comando e apenas usarsort -u
). Fromuniq(1)
: "Filtre as linhas correspondentes adjacentes de INPUT (ou entrada padrão), gravando em OUTPUT (ou saída padrão)."