GNU/Linux >> Tutoriels Linux >  >> Linux

Supprimer les champs en double dans une colonne donnée ?

Je voudrais supprimer d'une colonne donnée (2 $ dans l'exemple) les champs en double (séparés par des virgules).

Fichier d'entrée :

A    1,2,3,4   
B    4,5,6,3
C    2,15

Sortie attendue :

A    1,2,3,4
B    5,6
C    15

Réponse acceptée :

perl -lpe 's/sKS+/join ",", grep {!$seen{$_}++} split ",", $&/e'

Vous pouvez exécuter ce qui précède comme suit :

$ perl -lpe 's/sKS+/join ",", grep {!$seen{$_}++} split ",", $&/e' afile 
A    1,2,3,4
B    5,6
C    15

Comment ça marche

Premier appel de perl avec -lpe fait les 3 choses suivantes.

  • -l[octal] activer le traitement de fin de ligne, spécifie le terminateur de ligne
  • -p assume loop like -n mais print line aussi, comme sed
  • -e program une ligne de programme (plusieurs -e sont autorisés, omettez programfile)

Cela prend essentiellement le fichier, supprime les retours à la ligne, opère sur une ligne, puis y colle un caractère de retour à la ligne quand c'est fait. Il suffit donc de parcourir le fichier en boucle et d'exécuter notre code Perl tour à tour.

Quant au code Perl actuel :

  • s signifie un caractère d'espacement (les cinq caractères [ fnrt] et v dans les nouvelles versions de perl , comme [[:space:]] ).
  • K Gardez les choses à gauche du K, ne l'incluez pas dans $&
  • S+ un ou plusieurs caractères ne faisant pas partie de l'ensemble [ fnrtv]

Le join ",", va prendre les résultats et rejoindre chaque champ afin qu'il soit séparé par une virgule.

Le split ",", $& prendra les correspondances trouvées par le S+ et divisez-les en champs uniquement, sans virgule.

Le grep {!$seen{$_}++} prendra le numéro de chaque champ, l'ajoutera au hachage, $seen{} où le numéro de chaque champ est $_ au fur et à mesure que nous parcourons chacun d'eux. Chaque fois qu'un numéro de champ est "vu", il est compté via le ++ opérateur, $seen{$_}++ .

Le grep{!$seen{$_}++} renverra une valeur de champ si elle n'a été vue qu'une seule fois.

Modifié pour voir ce qui se passe

Si vous utilisez cette abomination modifiée, vous pouvez voir ce qui se passe lorsque ce paquebot Perl se déplace sur les lignes du fichier.

$ perl -lpe 's/sKS+/join ",", grep {!$seen{$_}++} split ",", $&/e; @a=keys %seen; @b=values %seen; print "keys: @a | vals: @b"' afile 
keys: 4 1 3 2 | vals: 1 1 1 1
A    1,2,3,4
keys: 6 4 1 3 2 5 | vals: 1 2 1 2 1 1
B    5,6
keys: 6 4 1 3 2 15 5 | vals: 1 2 1 2 2 1 1
C    15

Cela vous montre le contenu de $seen{} à la fin du traitement d'une ligne du fichier. Prenons la 2ème ligne du fichier.

B    4,5,6,3

Et voici comment ma version modifiée affiche cette ligne :

Touches
keys: 6 4 1 3 2 15 5 | vals: 1 2 1 2 2 1 1

Donc, cela veut dire que nous avons vu le champ # 6 (1 fois), le champ # 4 (2 fois), etc. et le champ # 5 (1 fois). Ainsi, lorsque grep{...} renvoie les résultats, il ne renverra les résultats de ce tableau que s'il était présent dans cette ligne (4,5,6,3) et si nous ne l'avons vu qu'une seule fois (6,1,15,5). L'intersection de ces 2 listes est (5,6) et c'est donc ce qui est renvoyé par grep .

Références

  • perlre – perldoc.perl.org
En relation :Comment modifier un fichier sur place ?
Linux
  1. Comment rechercher et supprimer des photos en double sous Linux

  2. Supprimer une clé expirée dans APT

  3. Comment supprimer les lignes en double dans un fichier texte ?

  4. Supprimer les lignes basées sur les doublons dans une colonne sans tri ?

  5. Supprimer les lignes en double adjacentes tout en conservant l'ordre ?

Comment supprimer les lignes en double dans MySQL

Comment rechercher et supprimer des fichiers en double / indésirables sous Linux à l'aide de l'outil "FSlint"

Commande Dissocier sous Linux (Supprimer le fichier)

Comment trouver des fichiers en double sous Linux et les supprimer

Comment supprimer les entrées en double dans le dialogue "ouvrir avec" Nautilus ?

Comment puis-je supprimer les fichiers en double dans des arborescences de répertoires distinctes ?