Je souhaite comparer fichier1 à fichier2 et générer un fichier3 contenant les lignes de fichier1 qui ne sont pas présentes dans fichier2.
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. S'ils ne le sont pas, 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 prenne en charge la substitution de processus (bash le fait).
L'utilitaire Unix diff
est conçu pour cela.
$ diff -u file1 file2 > file3
Voir le manuel et Internet pour les options, les différents formats de sortie, etc.
Considère 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."
Parfois diff
est l'utilitaire dont vous avez besoin, mais parfois join
est plus approprié. Les fichiers doivent être pré-triés ou, si vous utilisez un shell prenant en charge la substitution de processus, tel que bash, ksh ou zsh, vous pouvez effectuer le tri à la volée.
join -v 1 <(sort file1) <(sort file2)
Essayer
sdiff file1 file2
Cela fonctionne généralement beaucoup mieux dans la plupart des cas pour moi. Vous souhaiterez 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,
sdiff -w 185 file1.cfg file2.cfg
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 ni tri ni substitution de processus et prend en charge des flux infinis, comme ceci:
cat file1 | sd 'cat file2' > file3
Probablement pas un avantage sur cet exemple, mais considérez-le quand même; dans certains cas, vous ne pourrez pas utiliser comm
ni grep -F
ni diff
.
Voici un blogpost J'ai écrit sur les différents flux sur le terminal, ce qui introduit sd.
Beaucoup de réponses déjà, mais aucune d’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 exige que les fichiers soient triés ou pré-triés, ce qui peut ne pas être suffisant 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 réorganisation) est une combinaison de diff
, grep
et awk
(ou similaire ).
Si les lignes ne contiennent pas de "<", une ligne courte peut être:
diff urls.txt* | grep "<" | sed 's/< //g'
mais cela supprimera toutes les occurrences de "<" (moins de, espace) des lignes, ce qui n’est pas toujours OK (par exemple, le code source). L'option la plus sûre consiste à utiliser awk:
diff urls.txt* | grep "<" | awk '{for (i=2; i<NF; i++) printf $i " "; print $NF}'
Cette une ligne différencie les deux fichiers, puis filtre la sortie de diff du style éd, puis supprime le "<" final ajouté par diff. Cela fonctionne même si les lignes contiennent des "<" eux-mêmes.
Utilisez l'utilitaire Diff et extrayez uniquement les lignes commençant par <dans la sortie
Pourtant, pas de solution grep
?
lignes qui n'existent que dans file2:
grep -Fxvf file1 file2 > file3
lignes qui n'existent que dans fichier1:
grep -Fxvf file2 file1 > file3
lignes qui existent dans les deux fichiers:
grep -Fxf file1 file2 > file3
diff a1.txt a2.txt | grep '> ' | sed 's/> //' > a3.txt
J'ai essayé presque toutes les réponses dans ce fil, mais aucune n'était complète. Après quelques pistes ci-dessus on a travaillé pour moi. diff vous donnera la différence mais avec des caractères spéciaux indésirables. où vos différences réelles commencent par '>'. la prochaine étape consiste donc à grep les lignes commencent par '>' et sont ensuite supprimées par sed.
Vous pouvez utiliser diff
avec le formatage de sortie suivant:
diff --old-line-format='' --unchanged-line-format='' file1 file2
--old-line-format=''
, désactive la sortie pour fichier1 si la ligne est différente, comparez-la dans fichier2.--unchanged-line-format=''
, désactive la sortie si les lignes sont identiques.
Je suis surpris que personne n'ait mentionné diff -y
à 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):
same same
diff_1 | diff_2