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.
sort -u -t, -k1,1 file
-u
pour unique-t,
donc la virgule est le délimiteur-k1,1
pour le champ clé 1Ré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
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.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 3ou 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
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
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 }'