web-dev-qa-db-fra.com

Comparer deux fichiers texte

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.

6
Lynob

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).

6
Lety

Afin de pouvoir utiliser comm, vous devez d'abord trier les lignes.

comm -23 <(sort file1.csv) <(sort file2.csv) > file3.csv
7
choroba

À 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
3
αғsнιη

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
3
Jacob Vlijm