web-dev-qa-db-fra.com

Comment afficher les lignes en commun (reverse diff)?

J'ai une série de fichiers texte pour lesquels j'aimerais connaître les lignes communes plutôt que les lignes qui sont différentes entre eux. La ligne de commande unix ou windows est très bien.

foo:

linux-vdso.so.1 =>  (0x00007fffccffe000)
libvlc.so.2 => /usr/lib/libvlc.so.2 (0x00007f0dc4b0b000)
libvlccore.so.0 => /usr/lib/libvlccore.so.0 (0x00007f0dc483f000)
libc.so.6 => /lib/libc.so.6 (0x00007f0dc44cd000)

bar:

libkdeui.so.5 => /usr/lib/libkdeui.so.5 (0x00007f716ae22000)
libkio.so.5 => /usr/lib/libkio.so.5 (0x00007f716a96d000)
linux-vdso.so.1 =>  (0x00007fffccffe000)

Donc, étant donné que ces deux fichiers au-dessus de la sortie de l'utilitaire souhaité ressemblent à file1:line_number, file2:line_number == matching text _ (juste une suggestion, peu importe la syntaxe)

foo:1, bar:3 == linux-vdso.so.1 =>  (0x00007fffccffe000)

merci.

162
matt wilkie

Sur * nix, vous pouvez utiliser comm . La réponse à la question est:

comm -1 -2 file1.sorted file2.sorted 
# where file1 and file2 are sorted and piped into *.sorted

Voici l'utilisation complète de comm:

comm [-1] [-2] [-3 ] file1 file2
-1 Suppress the output column of lines unique to file1.
-2 Suppress the output column of lines unique to file2.
-3 Suppress the output column of lines duplicated in file1 and file2. 

Notez également qu’il est important de trier les fichiers avant d’utiliser comm, comme indiqué dans les pages de manuel.

196
Daniel Lew

Trouvé cette réponse sur ne question répertoriée en double . Je trouve que grep est plus convivial que comm, alors si vous voulez juste un ensemble de lignes correspondantes (utile pour comparer des CSV, par exemple), utilisez simplement

grep -F -x -f file1 file2

ou la version simplifiée de fgrep

fgrep -xf file1 file2

De plus, vous pouvez utiliser file2* pour balayer et rechercher des lignes communes avec plusieurs fichiers plutôt que deux.

Quelques autres variations pratiques incluent

  • -n drapeau pour indiquer le numéro de ligne de chaque ligne correspondante
  • -c pour ne compter que le nombre de lignes correspondant
  • -v pour afficher uniquement les lignes dans le fichier 2 qui diffèrent (ou utilisez diff).

Utiliser comm est plus rapide, mais cette rapidité se fait au détriment du tri de vos fichiers. Ce n'est pas très utile en tant que "diff inverse".

46
Ryder

A été demandé ici auparavant: commande Unix pour trouver des lignes communes dans deux fichiers

Vous pouvez aussi essayer avec Perl (crédit va ici )

Perl -ne 'print if ($seen{$_} .= @ARGV) =~ /10$/'  file1 file2
33
ChristopheD

Je viens d'apprendre la commande comm à partir de ce fil, mais je voulais ajouter quelque chose de plus: si les fichiers ne sont pas triés et que vous ne voulez pas toucher aux fichiers d'origine, vous pouvez diriger la sortie de la commande de tri. Cela laisse les fichiers originaux intacts. Fonctionne à Bash, je ne peux pas dire à propos d'autres obus.

comm -1 -2 <(sort file1) <(sort file2)

Cela peut être étendu pour comparer le résultat de la commande, au lieu de fichiers:

comm -1 -2 <(ls /dir1 | sort) <(ls /dir2 | sort)
16
Greg Mueller

Le moyen le plus simple de faire est:

awk 'NR==FNR{a[$1]++;next} a[$1] ' file1 file2

Les fichiers ne doivent pas être triés.

6
Gopu

Juste pour information, j'ai créé un petit outil pour Windows faisant la même chose que "grep -F -x -f fichier1 fichier2" (comme je n'ai rien trouvé d'équivalent à cette commande sous Windows)

Le voici: http://www.nerdzcore.com/?page=commonlines

L'utilisation est "CommonLines inputFile1 inputFile2 outputFile"

Le code source est également disponible (GPL)

1
Zivilyn Bane