Récupérer les différences entre 2 fichiers

Fermé
electronis Messages postés 1 Date d'inscription lundi 4 janvier 2021 Statut Membre Dernière intervention 4 janvier 2021 - Modifié le 8 janv. 2021 à 02:54
mamiemando Messages postés 33401 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 28 novembre 2024 - 8 janv. 2021 à 02:59
Bonjour,

Je souhaite récupérer uniquement les différences entre deux fichiers. Je m'explique, prenons :
  • le fichier A, qui contient "12azer45 65test"
  • le fichier B, b qui contient "123azerT45 658858585tTest"

... je voudrais récupérer un fichier qui contient 3T8858585T.

Est ce que cela est possible ?
Je suis ouvert à toute proposition,
D'avance merci

1 réponse

mamiemando Messages postés 33401 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 28 novembre 2024 7 804
8 janv. 2021 à 00:53
Bonjour,

Le problème que tu résous est un cas particulier du problème de recherche de plus longue sous séquence qui d'un point de vue théorique s'applique caractère par caractère (c'est juste que dans diff, chaque ligne peut être vue comme un "gros" caractère). Sans entrer trop dans les maths, la résolution du programme dynamique sous-jacent permet de déduire quels caractères sont ajoutés et supprimés.

Sous linux, la commande
diff
permet de déterminer les différences entre deux fichiers (ajouts, suppressions, modifications) en traitant ces fichiers ligne par ligne. Tu peux donc t'inspirer de cette discussion mais le raisonnement reste ligne par ligne.

Exemple :

(mando@aldur) (~) $ echo "12azer45 65test" > a.txt
(mando@aldur) (~) $ echo "123azerT45 658858585tTest" > b.txt
(mando@aldur) (~) $ diff <(cat a.txt) <(cat b.txt)
1c1
< 12azer45 65test
---
> 123azerT45 658858585tTest


Donc on va tricher un peu, on transformer le contenu des deux fichiers de sorte à écrire un caractère par ligne, comme expliqué ici.

(mando@aldur) (~) $ diff <(cat a.txt|sed 's/\(.\)/\1\n/g') <(cat b.txt|sed 's/\(.\)/\1\n/g')
2a3
> 3
6a8
> T
11a14,20
> 8
> 8
> 5
> 8
> 5
> 8
> 5
12a22
> T


Comme tu vois, les lignes qui nous intéressent sont celles qui commencent par > (donc on va utiliser
grep "^>"
pour les récupérer), après le premier espace (donc on va utiliser
cut -d" " -f2
).

(mando@aldur) (~) $ diff <(cat a.txt|sed 's/\(.\)/\1\n/g') <(cat b.txt|sed 's/\(.\)/\1\n/g') | grep "^>" | cut -d" " -f2
3
T
8
8
5
8
5
8
5
T


Il ne reste plus qu' à remettre le tout sur une ligne. J'ai essayé comme suggéré ici la commande
xargs
mais elle introduit des espaces.

(mando@aldur) (~) $ diff <(cat a.txt|sed 's/\(.\)/\1\n/g') <(cat b.txt|sed 's/\(.\)/\1\n/g') | grep "^>" | cut -d" " -f2 | xargs
3 T 8 8 5 8 5 8 5 T


Bref peut être que ça te suffit mais le cas échéant tu as au moins une bonne partie qui est faite :-)

Bonne chance
1
Oui je vois le principe, merci, je vais essayer demain
0
mamiemando Messages postés 33401 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 28 novembre 2024 7 804 > Electronis
8 janv. 2021 à 02:59
Parfait, note que sur le principe (en adaptant ton
grep
, tu peux aussi récupérer les suppressions (qui seront préfixées par "< ").

Après si tu es d'humeur à développer, tu peux récupérer une implémentation dans le langage de ton choix qui calcule une LCS. Par exemple, cette page donne une implémentation naïve de calcul de LCS écrite en python. Il s'agit, comme indiqué sur le site, d'une implémentation naïve, car de nombreux travaux de recherche proposent des algorithmes plus performants. Mais bon, tant que tu ne cherches que des "soustractions" et tant que tes fichiers restent courts, tu n'en as sûrement pas le besoin...

Bonne chance
0