Supprimez les lignes en double adjacentes tout en conservant la commande

11

J'ai un fichier avec une colonne avec des noms qui se répètent plusieurs fois. Je veux condenser chaque répétition en une seule, tout en conservant toutes les autres répétitions du même nom qui ne sont pas adjacentes à d'autres répétitions du même nom.

Par exemple, je veux tourner le côté gauche vers le côté droit:

Golgb1    Golgb1    
Golgb1    Akna
Golgb1    Spata20
Golgb1    Golgb1
Golgb1    Akna
Akna
Akna
Akna
Spata20
Spata20
Spata20
Golgb1
Golgb1
Golgb1
Akna
Akna
Akna

C'est ce que j'ai utilisé: perl -ne 'print if ++$k{$_}==1' file.txt > file2.txt Cependant, cette méthode ne conserve qu'un représentant de la gauche (c'est-à-dire que Golb1 et Akna ne sont pas répétés).

Existe-t-il un moyen de conserver des noms uniques pour chaque bloc, tout en conservant des noms qui se répètent dans plusieurs blocs non adjacents?

Âge87
la source

Réponses:

23

uniq fera cela pour vous:

$ uniq inputfile
Golgb1
Akna
Spata20
Golgb1
Akna
DopeGhoti
la source
2
wow, c'était d'une facilité embarrassante! Merci!
Age87
@ Age87 Unix est super! Cela ne fonctionne que parce que vous vous attendez à ce que les doublons soient adjacents, déjà (ou que vous ne souhaitez pas supprimer les doublons non adjacents). Normalement, la recommandation est d'utilisersort | uniq
jpaugh
1
Ou plus succinctement, sort -u(:
DopeGhoti
9

Awk Solution:

awk '$1 != name{ print }{ name = $1 }' file.txt

Le résultat:

Golgb1
Akna
Spata20
Golgb1
Akna
RomanPerekhrest
la source
6

Essayez ceci - enregistrez la ligne précédente et comparez avec la ligne actuelle

$ perl -ne 'print if $p ne $_; $p=$_' ip.txt
Golgb1
Akna
Spata20
Golgb1
Akna

Vous avez également marqué uniq- avez-vous essayé?

$ uniq ip.txt
Golgb1
Akna
Spata20
Golgb1
Akna
Sundeep
la source
1

Avec sed, cela peut être fait comme suit:

sed -e '$!N;/^\(.*\)\n\1$/!P;D' input_file

Ici, nous avons dans l'espace de motif à tout moment 2 lignes. Lorsque la comparaison entre eux échoue, nous imprimons la première et la coupons par l'avant et revenons en arrière et ajoutons la ligne suivante dans l'espace de motif. Rincer ... répéter

En utilisant Perl en mode slurp, nous traitons le fichier entier comme une longue chaîne sur laquelle est appliquée l'expression rationnelle qui fait la comparaison pour vous.

perl -0777pe 's//$1/ while /^(.*\n)\1+/gm' input_file
Rakesh Sharma
la source
0

Question sur la solution sed de Rakesh Sharma.

Que faire si vous avez un fichier d'entrée tel que:

-126.1 48.206
-126.106 48.21
-126.11 48.212
-126.114 48.214
-126.116 48.216
-126.118 48.216
-126.128 48.222
-126.136 48.226

Et vous voulez qu'un fichier de sortie soit:

-126.1 48.206
-126.106 48.21
-126.11 48.212
-126.114 48.214
-126.116 48.216
-126.128 48.222
-126.136 48.226

Notez les manquants:

-126.118 48.216

Je sais que la commande que je veux est similaire à votre solution:

sed -e '$!N;/^\(.*\)\n\1$/!P;D' input_file

Impossible de le modifier de la bonne manière pour imprimer les deux colonnes et de ne le trier de cette manière spéciale qu'avec les valeurs de la colonne 2. Des conseils?

MattS
la source
sed -e '$!N' -e '/.*\.\([0-9]*\)\n.*\.\1$/!{P;D;}' -e 's/\n.*//;s/^/\n/;D' supprimera les éléments répétés suivants. Remarque: cela nécessite GNU sed. Pour le POSIXcomportement, il a besoin d'une légère modification.
Rakesh Sharma