web-dev-qa-db-fra.com

Existe-t-il un moyen de "uniq" par colonne?

J'ai un fichier .csv comme ceci:

[email protected],2009-11-27 01:05:47.893000000,example.net,127.0.0.1
[email protected],2009-11-27 00:58:29.793000000,example.net,255.255.255.0
[email protected],2009-11-27 00:58:29.646465785,example.net,256.255.255.0
...

Je dois supprimer les e-mails en double (toute la ligne) du fichier (c'est-à-dire une des lignes contenant [email protected] dans l'exemple ci-dessus). Comment utiliser uniq uniquement sur le champ 1 (séparé par des virgules)? Selon man, uniq n'a pas d'options pour les colonnes.

J'ai essayé quelque chose avec sort | uniq mais cela ne fonctionne pas.

173
Eno
sort -u -t, -k1,1 file
  • -u pour unique
  • -t, donc la virgule est le délimiteur
  • -k1,1 pour le champ clé 1

Résultat du test:

[email protected],2009-11-27 00:58:29.793000000,xx3.net,255.255.255.0 
[email protected],2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1 
296
Carl Smotricz
awk -F"," '!_[$1]++' file
  • -F définit le séparateur de champs.
  • $1 est le premier champ.
  • _[val] cherche val dans le hachage _ (une variable normale).
  • ++ incrémente et retourne l'ancienne valeur.
  • ! retourne logique pas.
  • il y a une empreinte implicite à la fin.
93
ghostdog74

Considérer plusieurs colonnes.

Triez et donnez une liste unique basée sur les colonnes 1 et 3:

sort -u -t : -k 1,1 -k 3,3 test.txt
  • -t : le colon est un séparateur
  • -k 1,1 -k 3,3 basé sur la colonne 1 et la colonne 3
14
Prakash

ou si tu veux utiliser uniq:

<mycvs.cvs tr -s ',' ' ' | awk '{print $3" "$2" "$1}' | uniq -c -f2

donne:

1 01:05:47.893000000 2009-11-27 [email protected]
2 00:58:29.793000000 2009-11-27 [email protected]
1
9
Carsten C.

Si vous souhaitez conserver le dernier des doublons, vous pouvez utiliser

 tac a.csv | sort -u -t, -r -k1,1 |tac

Quelle était mon exigence

ici

tac inversera le fichier ligne par ligne

5
Sumukh

Voici un moyen très astucieux.

Commencez par formater le contenu de telle sorte que la colonne à comparer pour l’unicité soit une largeur fixe. Une façon de faire consiste à utiliser awk printf avec un spécificateur de largeur de champ/colonne ("% 15s").

Maintenant, les options -f et -w de uniq peuvent être utilisées pour ignorer les champs/colonnes précédents et pour spécifier la largeur de comparaison (largeur de colonne (s)).

Voici trois exemples.

Dans le premier exemple ...

1) Attribuez temporairement à la colonne d’intérêt une largeur fixe supérieure ou égale à la largeur maximale du champ.

2) Utilisez l'option -f uniq pour ignorer les colonnes précédentes et utilisez l'option -w uniq pour limiter la largeur à tmp_fixed_width.

3) Supprimez les espaces de fin de colonne pour "restaurer" sa largeur (en supposant qu’il n’y avait pas d’espace de fin auparavant).

printf "%s" "$str" \
| awk '{ tmp_fixed_width=15; uniq_col=8; w=tmp_fixed_width-length($uniq_col); for (i=0;i<w;i++) { $uniq_col=$uniq_col" "}; printf "%s\n", $0 }' \
| uniq -f 7 -w 15 \
| awk '{ uniq_col=8; gsub(/ */, "", $uniq_col); printf "%s\n", $0 }'

Dans le deuxième exemple ...

Créez une nouvelle colonne uniq 1. Ensuite, supprimez-la une fois le filtre uniq appliqué.

printf "%s" "$str" \
| awk '{ uniq_col_1=4; printf "%15s %s\n", uniq_col_1, $0 }' \
| uniq -f 0 -w 15 \
| awk '{ $1=""; gsub(/^ */, "", $0); printf "%s\n", $0 }'

Le troisième exemple est identique au deuxième, mais pour plusieurs colonnes.

printf "%s" "$str" \
| awk '{ uniq_col_1=4; uniq_col_2=8; printf "%5s %15s %s\n", uniq_col_1, uniq_col_2, $0 }' \
| uniq -f 0 -w 5 \
| uniq -f 1 -w 15 \
| awk '{ $1=$2=""; gsub(/^ */, "", $0); printf "%s\n", $0 }'
0
NOYB