Comparer plusieurs lignes
Résolu
papavers
Messages postés
24
Date d'inscription
Statut
Membre
Dernière intervention
-
[Dal] Messages postés 6205 Date d'inscription Statut Contributeur Dernière intervention -
[Dal] Messages postés 6205 Date d'inscription Statut Contributeur Dernière intervention -
Bonjour à tous,
Apres plusieurs heures de casse tête je m'en remet à vous.
J'ai un fichier texte à 2 colonnes. Je dois comparer les valeurs de la premiere colonne, et partout où les valeurs sont identiques, j'affiche le résultat sur une ligne.
exemple.
Input file
7051060508 8050842880
7051060508 7051038719
7052991542 8056725494
7052991542 8070996945
7052991542 8073010138
7052991577 8159484404
7052991600 8055099690
7052991600 8050277010
Output file
7051060508 8050842880 7051038719
7052991542 8056725494 8070996945 8073010138
7052991577 8159484404
7052991600 8055099690 8050277010
J'espère avoir été aussi clair que possible.
Merci déjà pour votre aide!!
Apres plusieurs heures de casse tête je m'en remet à vous.
J'ai un fichier texte à 2 colonnes. Je dois comparer les valeurs de la premiere colonne, et partout où les valeurs sont identiques, j'affiche le résultat sur une ligne.
exemple.
Input file
7051060508 8050842880
7051060508 7051038719
7052991542 8056725494
7052991542 8070996945
7052991542 8073010138
7052991577 8159484404
7052991600 8055099690
7052991600 8050277010
Output file
7051060508 8050842880 7051038719
7052991542 8056725494 8070996945 8073010138
7052991577 8159484404
7052991600 8055099690 8050277010
J'espère avoir été aussi clair que possible.
Merci déjà pour votre aide!!
A voir également:
- Comparer plusieurs lignes
- Écrire plusieurs lignes dans une cellule excel mac - Guide
- Comparer prix amazon - Guide
- Excel trier par ordre alphabétique en gardant les lignes - Guide
- Meilleur prix Amazon : payer moins cher avec Amazin'Europe - Accueil - Commerce
- Recherchev + somme plusieurs lignes - Forum Excel
4 réponses
avec doublons et lignes non triées
$ cat fichier 7051060508 8050842880 7051060508 7051038719 7052991542 8056725494 7052991542 8070996945 7052991542 8073010138 7051060508 8050842880 $ $ awk '{xx[$1, $2]++} !x[$1] {x[$1]=$1} xx[$1 ,$2]<2 {x[$1]=x[$1] FS $2}END{for (n in x)print x[n] }' fichier 7052991542 8056725494 8070996945 8073010138 7051060508 8050842880 7051038719 $
Salut papavers,
C'est assez simple avec Perl.
Tu traites chaque ligne avec un split sur l'espace, en utilisant la 1ère colonne comme clef d'un hash, et en y affectant le contenu de la 2ème colonne comme valeur du hash concaténée à la valeur existante (avec un espace).
Puis tu affiches le contenu du hash.
Dal
C'est assez simple avec Perl.
Tu traites chaque ligne avec un split sur l'espace, en utilisant la 1ère colonne comme clef d'un hash, et en y affectant le contenu de la 2ème colonne comme valeur du hash concaténée à la valeur existante (avec un espace).
Puis tu affiches le contenu du hash.
Dal
Tu peux faire comme cela :
#!/usr/bin/perl use strict; use warnings; my $ligne; my %hash; open(FICH, "/root/Documents/testperl/fichiertexte.txt") || die "Impossible d'ouvrir fichiertexte.txt: $!\n"; foreach $ligne (<FICH>) { chomp($ligne); my @colonnes = split(/ /, $ligne); $hash{$colonnes[0]} .= $colonnes[1] . " "; } my $clef; foreach $clef (sort keys %hash) { print "$clef $hash{$clef}\n"; }
hello
avec awk
avec awk
$ awk '!x[$1] {if (n++)print "" ; x[$1]=$1 ; printf $1 FS} {printf $2 FS}END{print ""}' fichier 7051060508 8050842880 7051038719 7052991542 8056725494 8070996945 8073010138 7052991577 8159484404 7052991600 8055099690 8050277010 $
Oui, comme cela la commande fonctionne sous csh (plus sous sh ou bash, où une autre erreur s'affiche).
Il me semble que ton algorithme suppose que les lignes dans le "fichier" sont dans l'ordre pour que les résultats soient exacts. Pour parer au cas où elles sont dans le désordre, je la précèderai aussi d'un sort qui "pipe" les données vers awk. Comme cela, avec bash :
Par contre, elle laisse un espace en fin de chaque lignes affichées, mais mes connaissance sont limitées en awk, et je ne vois pas comment faire pour supprimer le dernier espace. Je ne sais pas si c'est vraiment gênant pour papavers.
Je suis toujours épaté de ce que l'on peut faire avec awk, je ne savais pas qu'il gérait les tableaux associatifs. C'est un peu tarabiscoté, mais malin et compact !
Il me semble que ton algorithme suppose que les lignes dans le "fichier" sont dans l'ordre pour que les résultats soient exacts. Pour parer au cas où elles sont dans le désordre, je la précèderai aussi d'un sort qui "pipe" les données vers awk. Comme cela, avec bash :
sort fichier | awk '!x[$1] {if (n++)print "" ; x[$1]=$1 ; printf $1 FS} {printf $2 FS}END{print ""}'
Par contre, elle laisse un espace en fin de chaque lignes affichées, mais mes connaissance sont limitées en awk, et je ne vois pas comment faire pour supprimer le dernier espace. Je ne sais pas si c'est vraiment gênant pour papavers.
Je suis toujours épaté de ce que l'on peut faire avec awk, je ne savais pas qu'il gérait les tableaux associatifs. C'est un peu tarabiscoté, mais malin et compact !
Hello Dubcek, c'etait l'astuce que je recherchais avec awk. La premiere syntaxe fonctionne à mon niveau sous ksh.
Et côté performance même si on a des lignes identiques le resultat est pareil, contrairement a la commnde perl.
exemple
7051060508 8050842880
7051060508 7051038719
7052991542 8056725494
7052991542 8070996945
7052991542 8073010138
7051060508 8050842880
AWK
7051060508 8050842880 7051038719
7052991542 8056725494 8070996945 8073010138 8050842880
PERL
7051060508 8050842880 7051038719 8050842880
7052991542 8056725494 8070996945 8073010138
Et côté performance même si on a des lignes identiques le resultat est pareil, contrairement a la commnde perl.
exemple
7051060508 8050842880
7051060508 7051038719
7052991542 8056725494
7052991542 8070996945
7052991542 8073010138
7051060508 8050842880
AWK
7051060508 8050842880 7051038719
7052991542 8056725494 8070996945 8073010138 8050842880
PERL
7051060508 8050842880 7051038719 8050842880
7052991542 8056725494 8070996945 8073010138
Non, dans ton nouvel exemple l'algorithme utilisé dans la commande awk renvoie un résultat faux car la dernière ligne n'est pas triée et le dernier "8050842880" en colonne 2 est compris comme la suite de la série "7052991542" de la colonne 1, et affiché à la fin de la 2ème ligne de résultat, alors sa clef est "7051060508" et non "7052991542".
Pour que la commande awk renvoie des résultats corrects sur un fichier non trié, il faut le trier au préalable, comme indiqué dans mon message ci-dessus.
Si tu fais cela, tu verras que tu auras le même résultat que le script Perl.
Si tu veux éviter les doublons, tu passeras ton fichier par uniq également, après l'avoir filtré avec sort.
Avec le script Perl, le sort préalable n'est pas nécessaire, car l'algorithme proposé se sert du hash (le tableau associatif sous Perl) pour stocker les valeurs correspondant aux clefs. Si tu veux éviter les doublons, tu peux faire un test de la valeur du hash, pour vérifier qu'elle ne contient pas déjà la valeur que l'on ajoute.
Mais, donc, en faisant :
Tu devrais obtenir le même résultat, à l'exception des espaces additionnels qui restent en fin de lignes avec la commande awk.
Dal
Pour que la commande awk renvoie des résultats corrects sur un fichier non trié, il faut le trier au préalable, comme indiqué dans mon message ci-dessus.
Si tu fais cela, tu verras que tu auras le même résultat que le script Perl.
Si tu veux éviter les doublons, tu passeras ton fichier par uniq également, après l'avoir filtré avec sort.
Avec le script Perl, le sort préalable n'est pas nécessaire, car l'algorithme proposé se sert du hash (le tableau associatif sous Perl) pour stocker les valeurs correspondant aux clefs. Si tu veux éviter les doublons, tu peux faire un test de la valeur du hash, pour vérifier qu'elle ne contient pas déjà la valeur que l'on ajoute.
if ($hash{$colonnes[0]} !~ /$colonnes[1]/) { $hash{$colonnes[0]} .= $colonnes[1] . " "; }
Mais, donc, en faisant :
sort fichier | uniq | awk '!x[$1] {if (n++)print "" ; x[$1]=$1 ; printf $1 FS} {printf $2 FS}END{print ""}'
Tu devrais obtenir le même résultat, à l'exception des espaces additionnels qui restent en fin de lignes avec la commande awk.
Dal
je suis sûr qu'un spécialiste de Perl (que je ne suis pas) arriverait à faire plus court et moins compréhensible ;-P