J'ai essayé diff mais cela génère des nombres et d'autres symboles devant différentes lignes, ce qui me rend difficile la comparaison des fichiers.
Dim
Réponses:
216
diff (1) n'est pas la réponse, mais comm (1) l'est.
NAME
comm - compare two sorted files line by line
SYNOPSIS
comm [OPTION]... FILE1 FILE2
...-1 suppress lines unique to FILE1
-2 suppress lines unique to FILE2
-3 suppress lines that appear in both files
Alors
comm -2-3 file1 file2 > file3
Les fichiers d'entrée doivent être triés. Si ce n'est pas le cas, triez-les d'abord. Cela peut être fait avec un fichier temporaire, ou ...
comm -2-3<(sort file1)<(sort file2)> file3
à condition que votre shell supporte la substitution de processus (bash le fait).
Rappelez-vous que deux fichiers doivent être triés et sont uniques
andy
6
Vous pouvez regrouper les options:comm -23
Paolo M
Que signifie «trié»? Que les lignes ont le même ordre? Ensuite, c'est probablement bien pour la plupart des cas d'utilisation - comme pour vérifier quelles lignes ont été ajoutées en comparant avec une version plus ancienne sauvegardée. Si les lignes nouvellement ajoutées ne peuvent pas être entre les lignes existantes, c'est plus un problème.
Egor Hans
@EgorHans: si le fichier contient par exemple des lignes contenant des entiers tels que "3 \ n1 \ n3 \ n2 \ n", les lignes doivent d'abord être réordonnées par ordre croissant ou décroissant, par exemple "\ 1 \ n2 \ n3 \ n3 \ n" avec des doublons adjacent. C'est "trié" et les deux fichiers doivent être triés de la même manière. Lorsque le fichier le plus récent a de nouvelles lignes, peu importe si elles sont «entre les lignes existantes» car après le tri elles ne sont pas, elles sont triées.
sorpigal
48
L'utilitaire Unix diffest conçu exactement dans ce but.
$ diff -u file1 file2 > file3
Consultez le manuel et Internet pour les options, les différents formats de sortie, etc.
Cela ne fait pas le travail demandé; il insère un tas de caractères supplémentaires, même avec l'utilisation des commutateurs de ligne de commande suggérés dans d'autres réponses.
xenocyon le
20
Considérez ceci:
fichier a.txt:
abcd
efgh
fichier b.txt:
abcd
Vous pouvez trouver la différence avec:
diff -a --suppress-common-lines -y a.txt b.txt
La sortie sera:
efgh
Vous pouvez rediriger la sortie dans un fichier de sortie (c.txt) en utilisant:
diff -a --suppress-common-lines -y a.txt b.txt > c.txt
Cela répondra à votre question:
"... qui contient les lignes du fichier1 qui ne sont pas présentes dans le fichier2."
Il y a deux limitations à cette réponse: (1) cela ne fonctionne que pour les lignes courtes (moins de 80 caractères par défaut, bien que cela puisse être modifié) et, plus important, (2) il ajoute un "<" à la fin de chaque ligne qui doit être supprimée avec un autre programme (par exemple awk, sed).
sergut
Dans de nombreux cas, vous voudrez également utiliser -d, ce qui fera de diffson mieux pour trouver le plus petit diff. -i, -E, -w, -BEt --suppress-blank-emptypeut aussi être utile de temps en temps, mais pas toujours. Si vous ne savez pas ce qui correspond à votre cas d'utilisation, essayez d' diff --helpabord (ce qui est généralement une bonne idée lorsque vous ne savez pas ce qu'une commande peut faire).
Egor Hans
De plus, en utilisant --line-format =% L, vous empêchez diff de générer des caractères supplémentaires (au moins, l'aide dit que cela fonctionne comme ça, mais sur le point de l'essayer).
Parfois, diffc'est l'utilitaire dont vous avez besoin, mais parfois joinplus approprié. Les fichiers doivent être pré-triés ou, si vous utilisez un shell prenant en charge la substitution de processus comme bash, ksh ou zsh, vous pouvez effectuer le tri à la volée.
Vous devriez obtenir une médaille pour cela! C'était exactement ce que je cherchais ces 2 dernières heures
Zatarra
7
Essayer
sdiff file1 file2
Cela fonctionne généralement beaucoup mieux dans la plupart des cas pour moi. Vous voudrez peut-être trier les fichiers avant, si l'ordre des lignes n'est pas important (par exemple, certains fichiers de configuration de texte).
Belle utilité! J'aime la façon dont il marque les lignes de différenciation. Rend beaucoup plus facile la comparaison des configurations. Ceci avec le tri est un combo mortel (par exemple sdiff <(sort file1) <(sort file2))
jmagnusson
3
Si vous avez besoin de résoudre cela avec coreutils, la réponse acceptée est bonne:
comm -23<(sort file1)<(sort file2)> file3
Vous pouvez également utiliser sd (stream diff), qui ne nécessite pas de tri ni de substitution de processus et prend en charge des flux infinis, comme ceci:
cat file1 | sd 'cat file2'> file3
Probablement pas tellement d'un avantage sur cet exemple, mais considérez-le toujours; dans certains cas, vous ne pourrez pas utiliser commni grep -Fni diff.
Voici un article de blog que j'ai écrit sur les différents flux sur le terminal, qui présente sd.
Beaucoup de réponses déjà, mais aucune d'entre elles n'est parfaite à mon humble avis. La réponse de Thanatos laisse quelques caractères supplémentaires par ligne et la réponse de Sorpigal nécessite que les fichiers soient triés ou pré-triés, ce qui peut ne pas être adéquat dans toutes les circonstances.
Je pense que la meilleure façon d'obtenir les lignes qui sont différentes et rien d' autre (pas de caractères supplémentaires, pas de re-commande) est une combinaison de diff, grepet awk(ou similaire).
Si les lignes ne contiennent aucun "<", une courte ligne unique peut être:
diff urls.txt*| grep "<"| sed 's/< //g'
mais cela supprimera toutes les instances de "<" (moins de, espace) des lignes, ce qui n'est pas toujours OK (par exemple le code source). L'option la plus sûre est d'utiliser awk:
Cette ligne diffère les deux fichiers, puis filtre la sortie de style ed de diff, puis supprime le "<" de fin ajouté par diff. Cela fonctionne même si les lignes contiennent elles-mêmes des "<".
comm ne nécessite pas de tri (dans les versions plus récentes?) - utilisez simplement --nocheck-order. J'utilise beaucoup cela lors de la manipulation de csvs depuis la CLI
ak5
2
Je suis surpris que personne n'ait mentionné diff -yde produire une sortie côte à côte , par exemple:
diff -y file1 file2 > file3
Et dans file3(les différentes lignes ont un symbole |au milieu):
J'ai essayé presque toutes les réponses de ce fil, mais aucune n'était complète. Après quelques sentiers au-dessus, un a fonctionné pour moi. diff vous donnera une différence mais avec quelques charas spéciaux indésirables. où vos lignes de différence réelles commencent par «>». donc l'étape suivante consiste à grep les lignes commençant par '>' et suivies de la suppression de la même chose avec sed .
C'est une mauvaise idée. Vous devrez également modifier les lignes commençant par <. Vous verrez cela si vous permutez l'ordre des fichiers d'entrée. Même si vous faisiez cela, vous voudriez omettre grepen utilisant plus de sed: `diff a1 a2 | sed '/> / s ///' 'Cela peut encore casser des lignes contenant >ou <dans la bonne situation et laisse toujours des lignes supplémentaires décrivant les numéros de ligne. Si vous voulez essayer cette approche une meilleure façon serait la suivante: diff -C0 a1 a2 | sed -ne '/^[+-] /s/^..//p'.
sorpigal
0
Vous pouvez utiliser diffavec le formatage de sortie suivant:
--old-line-format='', désactiver la sortie pour fichier1 si la ligne était différente de la comparaison dans fichier2. --unchanged-line-format='', désactivez la sortie si les lignes étaient identiques.
Réponses:
diff (1) n'est pas la réponse, mais comm (1) l'est.
Alors
Les fichiers d'entrée doivent être triés. Si ce n'est pas le cas, triez-les d'abord. Cela peut être fait avec un fichier temporaire, ou ...
à condition que votre shell supporte la substitution de processus (bash le fait).
la source
comm -23
L'utilitaire Unix
diff
est conçu exactement dans ce but.Consultez le manuel et Internet pour les options, les différents formats de sortie, etc.
la source
Considérez ceci:
fichier a.txt:
fichier b.txt:
Vous pouvez trouver la différence avec:
La sortie sera:
Vous pouvez rediriger la sortie dans un fichier de sortie (c.txt) en utilisant:
Cela répondra à votre question:
la source
-d
, ce qui fera dediff
son mieux pour trouver le plus petit diff.-i
,-E
,-w
,-B
Et--suppress-blank-empty
peut aussi être utile de temps en temps, mais pas toujours. Si vous ne savez pas ce qui correspond à votre cas d'utilisation, essayez d'diff --help
abord (ce qui est généralement une bonne idée lorsque vous ne savez pas ce qu'une commande peut faire).Parfois,
diff
c'est l'utilitaire dont vous avez besoin, mais parfoisjoin
plus approprié. Les fichiers doivent être pré-triés ou, si vous utilisez un shell prenant en charge la substitution de processus comme bash, ksh ou zsh, vous pouvez effectuer le tri à la volée.la source
Essayer
Cela fonctionne généralement beaucoup mieux dans la plupart des cas pour moi. Vous voudrez peut-être trier les fichiers avant, si l'ordre des lignes n'est pas important (par exemple, certains fichiers de configuration de texte).
Par exemple,
la source
sdiff <(sort file1) <(sort file2)
)Si vous avez besoin de résoudre cela avec coreutils, la réponse acceptée est bonne:
Vous pouvez également utiliser sd (stream diff), qui ne nécessite pas de tri ni de substitution de processus et prend en charge des flux infinis, comme ceci:
Probablement pas tellement d'un avantage sur cet exemple, mais considérez-le toujours; dans certains cas, vous ne pourrez pas utiliser
comm
nigrep -F
nidiff
.Voici un article de blog que j'ai écrit sur les différents flux sur le terminal, qui présente sd.
la source
Pourtant, pas de
grep
solution?lignes qui n'existent que dans fichier2:
lignes qui n'existent que dans fichier1:
lignes qui existent dans les deux fichiers:
la source
Beaucoup de réponses déjà, mais aucune d'entre elles n'est parfaite à mon humble avis. La réponse de Thanatos laisse quelques caractères supplémentaires par ligne et la réponse de Sorpigal nécessite que les fichiers soient triés ou pré-triés, ce qui peut ne pas être adéquat dans toutes les circonstances.
Je pense que la meilleure façon d'obtenir les lignes qui sont différentes et rien d' autre (pas de caractères supplémentaires, pas de re-commande) est une combinaison de
diff
,grep
etawk
(ou similaire).Si les lignes ne contiennent aucun "<", une courte ligne unique peut être:
mais cela supprimera toutes les instances de "<" (moins de, espace) des lignes, ce qui n'est pas toujours OK (par exemple le code source). L'option la plus sûre est d'utiliser awk:
Cette ligne diffère les deux fichiers, puis filtre la sortie de style ed de diff, puis supprime le "<" de fin ajouté par diff. Cela fonctionne même si les lignes contiennent elles-mêmes des "<".
la source
Je suis surpris que personne n'ait mentionné
diff -y
de produire une sortie côte à côte , par exemple:Et dans
file3
(les différentes lignes ont un symbole|
au milieu):la source
Utilisez l'utilitaire Diff et extrayez uniquement les lignes commençant par <dans la sortie
la source
J'ai essayé presque toutes les réponses de ce fil, mais aucune n'était complète. Après quelques sentiers au-dessus, un a fonctionné pour moi. diff vous donnera une différence mais avec quelques charas spéciaux indésirables. où vos lignes de différence réelles commencent par «>». donc l'étape suivante consiste à grep les lignes commençant par '>' et suivies de la suppression de la même chose avec sed .
la source
<
. Vous verrez cela si vous permutez l'ordre des fichiers d'entrée. Même si vous faisiez cela, vous voudriez omettregrep
en utilisant plus de sed: `diff a1 a2 | sed '/> / s ///' 'Cela peut encore casser des lignes contenant>
ou<
dans la bonne situation et laisse toujours des lignes supplémentaires décrivant les numéros de ligne. Si vous voulez essayer cette approche une meilleure façon serait la suivante:diff -C0 a1 a2 | sed -ne '/^[+-] /s/^..//p'
.Vous pouvez utiliser
diff
avec le formatage de sortie suivant:--old-line-format=''
, désactiver la sortie pour fichier1 si la ligne était différente de la comparaison dans fichier2.--unchanged-line-format=''
, désactivez la sortie si les lignes étaient identiques.la source