J'ai 2 gros fichiers csv, file1.csv qui ressemble à ceci
1,2,3,4
1,4,5,6
1,7,8,9
1,11,13,17
file2.csv qui ressemble à ceci
1,2,3,4
1,7,8,9
2,4,9,10
13,14,17,18
Ce ne sont que des nombres aléatoires que j'ai composés, essentiellement les deux nombres identiques et triés. Je souhaite comparer fichier1.csv et fichier2.csv, puis copier les lignes présentes dans fichier1.csv mais pas dans fichier2.csv dans fichier3.csv. le délimiteur est évidemment une virgule
J'ai essayé
comm -2 -3 file.csv file2.csv > file3.csv
et j'ai essayé
diff -u file.csv file2.csv >> file3.csv
Les deux ne fonctionnaient pas car file3 était plus gros que file1 et file2. J'ai essayé différentes commandes diff
et comm
, parfois plus volumineux que fichier2 et de la même taille que fichier1, je sais que fichier3 doit être considérablement moins volumineux que fichier1 et fichier2. Et bien sûr, j'ai regardé file3, pas les résultats que je voulais
À ce stade, je sais que cela pourrait être fait avec diff
ou comm
mais je ne connais pas la commande à utiliser.
Essayez cette commande:
grep -v -f file2.csv file1.csv > file3.csv
Selon manuel de grep :
-f FILE, --file=FILE
Obtain patterns from FILE, one per line. The empty file
contains zero patterns, and therefore matches nothing. (-f is
specified by POSIX.)
-v, --invert-match
Invert the sense of matching, to select non-matching lines. (-v
is specified by POSIX.)
Comme Steeldriver l'a dit dans son commentaire, il vaut mieux ajouter aussi -x
et -F
qui:
-F, --fixed-strings
Interpret PATTERN as a list of fixed strings, separated by
newlines, any of which is to be matched. (-F is specified by
POSIX.)
-x, --line-regexp
Select only those matches that exactly match the whole line.
(-x is specified by POSIX.)
Donc, mieux vaut:
grep -xvFf file2.csv file1.csv > file3.csv
Cette commande utilise la ligne file2.csv
comme modèle et la ligne d'impression de file1.csv
qui ne correspond pas (-v
).
Afin de pouvoir utiliser comm
, vous devez d'abord trier les lignes.
comm -23 <(sort file1.csv) <(sort file2.csv) > file3.csv
À l'aide de la commande diff
, faites _grep
et aucune opération de stockage n'est requise.
Sortie si des lignes existent dans le fichier 1 mais pas dans le fichier 2:
$ diff file{1,2}.csv | grep -Po "^< \K.*"
1,4,5,6
1,11,13,17
Et afficher si des lignes existent dans le fichier 2 mais pas dans le fichier 1, en changeant simplement l'angle gauche (<
) en angle droit (>
):
$ diff file{1,2}.csv | grep -Po "^> \K.*"
2,4,9,10
13,14,17,18
Une option python:
#!/usr/bin/env python3
import sys
def readfile(file):
with open(file) as src:
return [line.strip() for line in src.readlines()]
lines_1 = readfile(sys.argv[1]); lines_2 = readfile(sys.argv[2])
for line in lines_1:
if not line in lines_2:
print(line)
Sortie:
1,4,5,6
1,11,13,17
Collez le script dans un fichier vide en tant que extract.py
, rendez-le exécutable et exécutez-le à l'aide de la commande suivante:
<script> <file_1> <file_2>
Ou, pour l'écrire directement dans file_3:
<script> <file_1> <file_2> >file_3