Afficher les lignes communes (similitudes) de deux fichiers texte (l'opposé de diff)?

21

Diff est un excellent outil pour afficher les changements entre deux fichiers. Mais comment afficher les similitudes de deux fichiers texte (tout en ignorant les différences)?

Exemple d'entrée d'entrée:

a:
Foo Bar
X
Hello
World
42

b:
Foo Baz
Hello
World
23

Pseudo sortie (quelque chose comme ça):

@@ 2,3
=Hello World

Il ne suffit pas de trier les deux fichiers et d'utiliser la communication, car dans ce cas, les informations de ligne sont perdues.

maxschlepzig
la source

Réponses:

24

Que diriez-vous d'utiliser diff, même si vous ne voulez pas de diff? Essaye ça:

diff --unchanged-group-format='@@ %dn,%df 
  %<' --old-group-format='' --new-group-format='' \
  --changed-group-format='' a.txt b.txt

Voici ce que j'obtiens avec vos exemples de données:

$ cat a.txt 
Foo Bar
X
Hello
World
42
$ cat b.txt 
Foo Baz
Hello
World
23
$ diff --unchanged-group-format='@@ %dn,%df
%<' --old-group-format='' --new-group-format='' \
  --changed-group-format='' a.txt b.txt
@@ 2,3
Hello
World
Mike Gray
la source
2
Vous pouvez éviter d'incorporer une nouvelle ligne littérale comme celle-ci:...%df'$'\n''%<'...
pause jusqu'à nouvel ordre.
1
Vous pouvez également le faire comme ceci: ... --unchanged-group-format="@@ %dn,%df%c'\012'%<" ...(Notez les guillemets doubles.)
pause jusqu'à nouvel ordre.
Super truc! Je ne connaissais pas ces options, car je viens de regarder la page de manuel diff ...
maxschlepzig
J'utilise diff --version diff (GNU diffutils) 2.8.1 Et j'obtiens l'erreur suivante: diff: options de style de sortie conflictuelles diff: Essayez `diff --help 'pour plus d'informations.
Sujay
J'obtenais «erreur: diff: options de style de sortie conflictuelles diff» parce que j'avais un alias de différence défini. Utilisez which diffpour voir si c'est votre problème.
justinjhendrick
14
grep -Fxf file1 file2

-Fsignifie correspondre à des chaînes simples (pas à des expressions rationnelles), -xsignifie uniquement des correspondances sur toute la ligne, -fsignifie prendre des «modèles» (c'est-à-dire des lignes) du fichier nommé comme argument

tobyodavies
la source
3
N'est-ce pas -fet -Féchangé ?. Au moins dans ma grepversion est comme ça. Je dois fournir une file2entrée à l' -fargument, comme cat file1 | grep -Fxf file2, puis fonctionne.
Birei
Cela ne fonctionne pas pour moi.
Chaminda Bandara
7

commpeut être utilisé. man commpour toutes les options, mais vous voudrez utiliser comm -12 ...pour afficher uniquement les lignes qui existent dans les deux entrées.

Comme les gens l'ont souligné, vous devez d'abord transmettre vos commentaires sort.

Oli
la source
1
Hm, cela ne fonctionne que pour les lignes communes qui sont au même numéro de ligne dans les deux fichiers.
maxschlepzig
2
comm semble être uniquement pour les fichiers triés et ne pas donner cette sortie utile pour le cas d'utilisation de l'OP. Son exemple: $ comm -12 ab Hello World comm: le fichier 1 n'est pas dans l'ordre trié comm: le fichier 2 n'est pas dans l'ordre trié
Marcel Stimberg
@maxschlepzig: vous devez trier vos fichiers avant de les transmettre à comm.
Hemant
2
En triant, vous vous débarrassez de toutes les informations sur la position des lignes communes. Vous ne trieriez pas non plus les fichiers avant de les comparer avec diff.
Marcel Stimberg
7

Je ne pense pas qu'il existe une seule commande qui fasse ce que vous voulez qu'elle fasse. Vous pouvez cependant essayer de combiner la sortie de diffavec grep. Si vos fichiers texte contiennent aucun des caractères |, <, >, ce qui suit vous donne une sortie un peu utile:

$ diff --side-by-side a b | grep -n -v "[|<>]"
3:Hello                             Hello
4:World                             World
Marcel Stimberg
la source
Essayez ceci:diff --width=155 --left-column --side-by-side a b | grep -n -v '|' | sed 's/ *($//'
pause jusqu'à nouvel ordre.
cela semble mieux - mais vous devez inclure <et> dans le grep pour vous débarrasser également des lignes ajoutées dans les deux fichiers.
Marcel Stimberg
2

Dick Grune a écrit une famille d'outils pour ce genre de chose:

http://dickgrune.com/Programs/similarity_tester/

Il existe des versions qui analysent la syntaxe de divers langages, de sorte que des choses comme les variables renommées peuvent être considérées comme inchangées.

Il est empaqueté comme similarity-testerdans Debian et Ubuntu.

Douglas Bagnall
la source