BASH : Comparer 2 fichiers et afficher les similarités - Codes et scripts - Linux et OS Alternatifs
Marsh Posté le 04-02-2015 à 11:18:24
sinon tu as l'utilitaire "comm", qui est l'inverse de "diff"
Marsh Posté le 13-04-2015 à 15:40:41
il te faut une deuxième boucle pour itérer toutes les lignes du second fichier.
Pour l'instant tu itères sur toutes les lignes du premier fichier que tu compares a la première ligne du second fichier (second read).
Donc seul la première ligne du premier fichier matche à priori.
Tu as donc besoin d'une deuxième boucle while read do pour itérer les lignes de ton second fichier.
Marsh Posté le 13-04-2015 à 22:03:50
salut,
d'une part, le script original est faux : la boucle ne finira jamais, car read lit la première ligne du fichier.
le fichier doit être versé dans la boucle while :
Code :
|
la suggestion de netmonk ne fonctionnera pas, parce que la deuxième boucle lira le flux dans lequel est versé le fichier.
il faut utiliser des descripteurs de fichier.
à condition que les fichiers ont le même nombre de lignes ceci devrait fonctionner (je te laisse faire la comparaison) :
Code :
|
Marsh Posté le 14-04-2015 à 00:21:03
La réponse de blacklord n est pas satisfaisante ?
black_lord a écrit : sinon tu as l'utilitaire "comm", qui est l'inverse de "diff" |
Marsh Posté le 14-04-2015 à 10:53:48
OOPS
Citation :
|
ce n'est pas ça non plus : j'ai confondu avec la lecture depuis stdin, qui ne fonctionne pas lors de la lecture d'un fichier.
par contre, après test (de l'importance de tester les codes !!!), la suggestion de netmonk ne fonctionnera quand même pas, car pour chaque ligne du fichier #1, le fichier #2 sera lu entièrement.
vu qu'il est question de relever «les lignes similaires», comm est sans doute une meilleure alternative.
Marsh Posté le 14-04-2015 à 11:15:59
o'gure a écrit : La réponse de blacklord n est pas satisfaisante ? |
c'est trop efficace
Marsh Posté le 14-04-2015 à 12:09:10
hum un algo basique et brute force consistant à trouver les lignes identiques dans deux fichiers je pense que deux boucles while do imbriquées qui comparent chaques lignes du premier fichier avec toutes les lignes du deuxieme fichier est plutot satisfaisant.
Tu peux rajouter un break dans le while imbriqué pour sortir directement de celui-ci dés que tu trouves une ligne qui match.
C'est juste que là j'ai pas la main sur une console, mais ce soir je sors un bout de code qui fonctionne.
Cependant je suis d'accord pour utiliser comm commande native sera de facto beaucoup plus efficace.
Marsh Posté le 14-04-2015 à 14:37:32
[0]$ cat test1 |
Marsh Posté le 14-04-2015 à 18:24:47
ça n'enlève rien à ce que j'ai dit.
si on retire le test (ou si on met un set -x), on voit tout de suite ce que je voulais vous faire éviter :
Code :
|
ce n'est pas du tout satisfaisant.
Marsh Posté le 14-04-2015 à 21:13:18
Forcement tu fais une combinaison de toutes les lignes du premier fichier avec toutes les lignes du second fichier.
Mon code est un peu plus optimisé puisque on sort du while imbriqué dès que l'on trouve un match.
Cependant je ne comprend en rien tes histoires de descripteur de fichier. Tu as une page de manuel ou un lien vers de la doc ?
Marsh Posté le 14-04-2015 à 21:17:48
sinon tu as l'utilitaire "comm", qui est l'inverse de "diff"
Marsh Posté le 14-04-2015 à 21:31:25
Et d'un point de vue purement algorithmique je ne suis pas sûr que "comm" fasse vraiment mieux
Marsh Posté le 14-04-2015 à 21:56:16
tu vas trouver des explications à propos des descripteurs de fichiers dans l'ABS.
quand une ligne d'un descripteur de fichier est lue, elle est retirée de ce dernier.
de manière POSIX, on ferait ainsi :
Code :
|
parce que POSIX read n'a pas d'option -u pour lire les df.
on pourrait aussi passer les fichier dans un df en utilisant exec.
il y a quand même plus de chances que comm fonctionne de cette façon.
les langages un peu plus bas niveau que le shell, comme perl, python, php, ouvrent un fichier dans un descripteur de fichier, puis parcourent ce descripteur de fichier.
Marsh Posté le 14-04-2015 à 22:51:08
Watael : dernière question: en quoi ton bout de code fait ce que demande le post initial ?
C'est bien beau de m'empapaouter avec tes filesdesc mais moi je vois que ton résultat ne correspond en rien au problème initiale.
Merci donc de fournir un code qui réponde au problème initial et qui de surcroît spécifie à tes remarques.
Marsh Posté le 14-04-2015 à 23:08:02
le problème de barbanegra était de lire deux fichiers dans une seul boucle while :
Citation : Cependant lorsque j'exécute ce code, seule la première ligne (qui est la même dans les deux fichiers) est affichée en boucle. |
s'il veut faire ça en shell, la meilleure solution est d'utiliser des df, et pas d'ouvrir autant de fois un fichier qu'il y a de lignes dans l'autre !
Marsh Posté le 14-04-2015 à 23:14:37
Tu me trolles méchamment là l'ami, je cite :
Citation : J'ai 2 fichiers "queue -p" d'un serveur de mail (file d'attente des mails), je dois comparer 2 de ces fichiers (enregistrés avec quelques minutes de décalage) afin de relever les mails qui n'arrivent pas à partir. |
Voilà! ce n'est pas parce que barbanegra n'a pas réussi a coder ce qu'il voulait réellement faire (incompréhension de l'utilisation de read) que son besoin n'est pas exprimé clairement.
Et c'est d'ailleurs ce que je dis dans mon premier post: son code ne correspond en rien à ce qu'il cherche à faire : identifier toutes les lignes du fichier 1 qui sont présentes dans le fichier 2 (et réciproquement) ou de manière plus logique faire une intersection du fichier1 et du fichier2.
Et ni ton code ni le sien ne répondent à ce problème.
Maintenant je ne suis pas dans le cerveau de barbe-noire, donc il existe une marge d'erreur.
Enfin j'ai utilisé tes fameux FD :
while read -r line1 <&9 ; do |
Ce qui me donne exactement la même sortie de bash -x que sans les redirections FD.
Marsh Posté le 14-04-2015 à 23:21:20
Sinon il y a grep aussi :
plonky@netmonk ~ $ grep -f test1 test2 |sort|uniq |
comm n'a pas l'air efficace :
plonky@netmonk ~ $ comm -12 test1 test2 |
Et un petit bug dans comm :
plonky@netmonk ~ $ comm -12 --nocheck-order test1 test2 |
Il n'affiche pas "5 5" qui est commun aux deux fichiers.
Marsh Posté le 14-04-2015 à 23:38:33
'The infamous "Advanced" Bash Scripting Guide should be avoided unless you know how to filter out the junk. It will teach you to write bugs, not scripts. In that light, the BashGuide was written: http://mywiki.wooledge.org/BashGuide'
#bash@freenode
Marsh Posté le 14-04-2015 à 23:47:49
Citation : Ce qui me donne exactement la même sortie de bash -x que sans les redirections FD. |
normal, puisque tu génères un fd pour chaque ligne du premier fichier; les fd sont utiles parce qu'ils sont lus une seule fois.
comm ne convient pas non plus, alors, puisqu'il lit les deux fichiers ligne par ligne (ligne1.fichier1 ligne1.fichier2, etc).
Citation : Forcing `comm' to process wrongly sorted input files containing |
3 3 ne devrait pas apparaître puisqu'ils ne sont pas sur la même ligne.
je plussoie la solution grep, pour faire ce que tu as compris.
Marsh Posté le 14-04-2015 à 23:53:58
Pour enterrer la hache de guerre : http://mywiki.wooledge.org/BashFAQ/036
J'avais oublié le coup du uniq -d :
plonky@netmonk ~ $ sort test1 test2|uniq -d |
Marsh Posté le 04-02-2015 à 09:26:18
Bonjour, je débute en BASH et dois réaliser une opération à l'aide d'un script.
Le problème étant le suivant :
J'ai 2 fichiers "queue -p" d'un serveur de mail (file d'attente des mails), je dois comparer 2 de ces fichiers (enregistrés avec quelques minutes de décalage) afin de relever les mails qui n'arrivent pas à partir.
J'ai eu le raisonnement suivant : Je lis le premier fichier, et, ligne par ligne je le compare à toutes les lignes du second fichier et j'envoie les lignes similaires dans un autre fichier appelé "same.txt". J'ai réalisé ce script :
Cependant lorsque j'exécute ce code, seule la première ligne (qui est la même dans les deux fichiers) est affichée en boucle.
Pourriez-vous m'orienter ?
Message édité par black_lord le 04-02-2015 à 11:19:06