Comparer plusieurs lignes
Résolu/Fermé
papavers
Messages postés
24
Date d'inscription
mardi 6 mai 2008
Statut
Membre
Dernière intervention
10 mai 2012
-
9 mai 2012 à 17:50
[Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024 - 10 mai 2012 à 18:58
[Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024 - 10 mai 2012 à 18:58
A voir également:
- Comparer plusieurs lignes
- Comparer prix amazon - Guide
- Écrire plusieurs lignes dans une cellule excel mac - Guide
- Excel trier par ordre alphabétique en gardant les lignes - Guide
- Figer plusieurs lignes excel - Guide
- Filtre excel ne prend pas en compte toutes les lignes ✓ - Forum Excel
4 réponses
dubcek
Messages postés
18718
Date d'inscription
lundi 15 janvier 2007
Statut
Contributeur
Dernière intervention
22 mars 2024
5 615
10 mai 2012 à 15:22
10 mai 2012 à 15:22
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 $
papavers
Messages postés
24
Date d'inscription
mardi 6 mai 2008
Statut
Membre
Dernière intervention
10 mai 2012
1
9 mai 2012 à 18:45
9 mai 2012 à 18:45
Bonjour, aucune idée pour le moment :-(
[Dal]
Messages postés
6174
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
2 février 2024
1 083
9 mai 2012 à 19:09
9 mai 2012 à 19:09
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
[Dal]
Messages postés
6174
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
2 février 2024
1 083
9 mai 2012 à 19:26
9 mai 2012 à 19:26
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"; }
[Dal]
Messages postés
6174
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
2 février 2024
1 083
Modifié par [Dal] le 9/05/2012 à 19:34
Modifié par [Dal] le 9/05/2012 à 19:34
si cela t'ennuie d'avoir un espace terminal, tu peux le supprimer avant de l'afficher.
ta boucle foreach d'affichage peut alors ressembler à cela :
ta boucle foreach d'affichage peut alors ressembler à cela :
foreach $clef (sort keys %hash) { $_ = "$clef $hash{$clef}"; chop; print $_ ."\n"; }
papavers
Messages postés
24
Date d'inscription
mardi 6 mai 2008
Statut
Membre
Dernière intervention
10 mai 2012
1
9 mai 2012 à 23:23
9 mai 2012 à 23:23
Mr Dal, tu me sauve la "vie"! J'avoue que j'utilise pas vraiment perl, et je nai pas pu trouver la bonne combinaison avec awk.
mAis là j'ai bien pris le temps de comprendre ton script.
Encore merci
mAis là j'ai bien pris le temps de comprendre ton script.
Encore merci
dubcek
Messages postés
18718
Date d'inscription
lundi 15 janvier 2007
Statut
Contributeur
Dernière intervention
22 mars 2024
5 615
10 mai 2012 à 08:27
10 mai 2012 à 08:27
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 $
[Dal]
Messages postés
6174
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
2 février 2024
1 083
10 mai 2012 à 10:03
10 mai 2012 à 10:03
Salut dubcek,
Avec un shell csh sous FreeBSD et avec le awk de Brian Kernighan (pas le gawk que l'on trouve sous Linux), ta ligne donne "x[: Event not found.". Elle fonctionne en revanche sur la même machine avec un shell sh et bash avec le même awk.
Dal
Avec un shell csh sous FreeBSD et avec le awk de Brian Kernighan (pas le gawk que l'on trouve sous Linux), ta ligne donne "x[: Event not found.". Elle fonctionne en revanche sur la même machine avec un shell sh et bash avec le même awk.
Dal
dubcek
Messages postés
18718
Date d'inscription
lundi 15 janvier 2007
Statut
Contributeur
Dernière intervention
22 mars 2024
5 615
10 mai 2012 à 10:19
10 mai 2012 à 10:19
j'ai le même message avec tcsh, essayer
awk '\!x[$1] {if (n++)print "" ; x[$1]=$1 ; printf $1 FS} {printf $2 FS}END{print ""}' fichier
[Dal]
Messages postés
6174
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
2 février 2024
1 083
Modifié par [Dal] le 10/05/2012 à 11:28
Modifié par [Dal] le 10/05/2012 à 11:28
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 !
papavers
Messages postés
24
Date d'inscription
mardi 6 mai 2008
Statut
Membre
Dernière intervention
10 mai 2012
1
10 mai 2012 à 11:54
10 mai 2012 à 11:54
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
[Dal]
Messages postés
6174
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
2 février 2024
1 083
Modifié par [Dal] le 10/05/2012 à 12:56
Modifié par [Dal] le 10/05/2012 à 12:56
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
10 mai 2012 à 17:52
10 mai 2012 à 18:58
je suis sûr qu'un spécialiste de Perl (que je ne suis pas) arriverait à faire plus court et moins compréhensible ;-P