2009-09-17 6 views
2

Je veux supprimer toutes les lignes où toute la deuxième colonne 05408736032 sont les mêmessuppression des lignes en double à partir du fichier/grep

0009300 | 05408736032 | 89 | 01 | 001 | 0 | 0 | 0 | 1 | NNNNNNYNNNNNNNNN | asdf | 0009367 | 05408736032 | 89 | 01 | 001 | 0 | 0 | 0 | 1 | NNNNNNNNNNNNNNNN | adff |

ces lignes ne sont pas consécutives. C'est bien d'enlever toutes les lignes. Je ne dois pas en garder un d'entre eux.

Désolé mon unix fu est vraiment faible de non utilisation :).

+0

daveb - pourquoi la balise «sort»? – mob

+0

Double posté: http://serverfault.com/questions/66301/removing-duplicate-lines-from-file-with-grep –

+0

@Dennis quel est le problème avec le double affichage? Je ne comprends pas. – Surya

Répondre

1

Si les colonnes ne sont pas fixes largeur, vous pouvez toujours utiliser tri:

sort -t '|' --key=10,10 -g FILENAME 
  1. Le -t drapeau va définir le séparateur. Le -g est juste pour l'ordre numérique normal.
+0

Utilisez '-k' pour une portabilité maximale (POSIX-compatible) (et non '='). Aussi, pourquoi 10,10 pour la deuxième colonne? –

+0

Deux raisons. Un, Lorsque vous utilisez -t sort utilisera les champs pas les caractères (ie 10 n'est pas un nombre plus élevé). Deux, la fin (, 10) est spécifié pour arrêter le tri en utilisant le reste de la ligne à partir de ce point. – daveb

2

En supposant qu'ils sont consécutifs et que vous voulez supprimer les suivantes, le script awk suivant fera:

awk -F'|' 'NR==1 {print;x=$2} NR>1 {if ($2 != x) {print;x=$2}}' 

Il fonctionne en imprimant la première ligne et le stockage de la deuxième colonne. Ensuite, pour les lignes suivantes, il saute celles où la valeur stockée et la deuxième colonne sont les mêmes (si différent, il imprime la ligne et met à jour la valeur stockée). Si elles ne sont pas consécutives, j'opterais pour une solution Perl où vous conservez un tableau associatif pour détecter et supprimer les doublons - je le code mais ma fille de 3 ans vient de se réveiller, il est minuit et elle a un rhume - vous voir tous demain, si je survit à la nuit :-)

+0

oh ils ne sont pas postérieurs – Surya

8

Si toutes vos données d'entrée sont formatées comme ci-dessus - c'est-à-dire des champs de taille fixe - et l'ordre des lignes dans la sortie n'a pas d'importance , sort --key=8,19 --unique devrait faire l'affaire. Si l'ordre est important, mais que les lignes en double sont toujours consécutives, uniq -s 8 -w 11 fonctionnera. Si les champs ne sont pas à largeur fixe mais que les lignes en double sont toujours consécutives, le script awk de Pax fonctionnera. Dans le cas le plus général, nous sommes probablement en train de regarder quelque chose d'un peu trop compliqué pour un one-liner.

1

Unix comprend python, de sorte que les quelques-liners suivants peuvent être juste ce dont vous avez besoin:

f=open('input.txt','rt') 
d={} 
for s in f.readlines(): 
    l=s.split('|') 
    if l[2] not in d: 
    print s 
    d[l[2]]=True 

Cela fonctionne sans nécessiter de longueur fixe, et même si des valeurs identiques ne sont pas voisins.

+0

Cela ne supprimera pas toutes les lignes avec des valeurs en double - il imprimera la première instance. –

+0

en effet. La question dit "il est bon d'enlever toutes les instances" - donc supprimer tout n'est pas une exigence, c'est OK de laisser un représentant de chaque. Au moins, c'est comme ça que je l'ai compris. – redtuna

0

ce awk imprimer uniquement les lignes où la seconde colonne est pas 05408736032

awk '{if($2!=05408736032}{print}' filename 
+0

Avez-vous besoin de guillemets autour du nombre? Est-ce qu'il est interprété comme un nombre octal en raison du zéro de tête? Ou n'est-il pas interprété comme octal à cause des 8 apparaissant (invalide en octal, bien sûr), mais qu'en est-il s'il n'y avait pas 8 ou 9 dans le nombre? –

0

Prend deux passes sur le fichier d'entrée: 1) trouver les valeurs en double, 2) les enlever

awk -F\| ' 
    {count[$2]++} 
    END {for (x in count) {if (count[x] > 1) {print x}}} 
' input.txt >input.txt.dups 

awk -F\| ' 
    NR==FNR {dup[$1]++; next} 
    !($2 in dup) {print} 
' input.txt.dups input.txt 

Si vous utilisez bash, vous pouvez omettre le fichier temporaire: combiner en une seule ligne processus à l'aide substitution: (respiration profonde)

awk -F\| 'NR==FNR {dup[$1]++; next} !($2 in dup) {print}' <(awk -F\| '{count[$2]++} END {for (x in count) {if (count[x] > 1) {print x}}}' input.txt) input.txt 

(ouf!)

0

Mettez les lignes dans un hachage, en utilisant la ligne comme clé et la valeur, itérer puis sur le hachage (cela devrait fonctionner dans presque toutes les langues de programmation, awk, Perl, etc.)

2

Ceci est le code qui est utilisé pour supprimer les mots en double dans la ligne ..

awk '{for (i=1; i<=NF; i++) {x=0; for(j=i-1; j>=1; j--) {if ($i == $j){x=1} } if(x != 1){printf ("%s ", $i) }}print ""}' sent 
Questions connexes