GNU/Linux >> Tutoriels Linux >  >> Linux

Comment supprimer les lignes qui apparaissent sur le fichier B d'un autre fichier A ?

Si les fichiers sont triés (ils le sont dans votre exemple) :

comm -23 file1 file2

-23 supprime les lignes qui sont dans les deux fichiers, ou seulement dans le fichier 2. Si les fichiers ne sont pas triés, dirigez-les vers sort d'abord...

Voir la page de manuel ici


à la rescousse !

Cette solution ne nécessite pas d'entrées triées. Vous devez d'abord fournir le fichier B.

awk 'NR==FNR{a[$0];next} !($0 in a)' fileB fileA

renvoie

A
C

Comment ça marche ?

NR==FNR{a[$0];next} idiom sert à stocker le premier fichier dans un tableau associatif en tant que clés pour un test "contient" ultérieur.

NR==FNR vérifie si nous analysons le premier fichier, où le compteur de lignes global (NR) est égal au compteur de lignes de fichier actuel (FNR).

a[$0] ajoute la ligne actuelle au tableau associatif en tant que clé, notez que cela se comporte comme un ensemble, où il n'y aura pas de valeurs en double (clés)

!($0 in a) nous sommes maintenant dans le(s) fichier(s) suivant(s), in est un test contient, ici il vérifie si la ligne actuelle est dans l'ensemble que nous avons rempli dans la première étape à partir du premier fichier, ! annule la condition. Ce qui manque ici est l'action, qui par défaut est {print} et généralement pas écrit explicitement.

Notez que cela peut maintenant être utilisé pour supprimer les mots de la liste noire.

$ awk '...' badwords allwords > goodwords

avec une légère modification, il peut nettoyer plusieurs listes et créer des versions nettoyées.

$ awk 'NR==FNR{a[$0];next} !($0 in a){print > FILENAME".clean"}' bad file1 file2 file3 ...

Une autre façon de faire la même chose (nécessite également une entrée triée) :

join -v 1 fileA fileB

Dans Bash, si les fichiers ne sont pas pré-triés :

join -v 1 <(sort fileA) <(sort fileB)

grep -Fvxf <lines-to-remove> <all-lines>

  • fonctionne sur des fichiers non triés (contrairement à comm )
  • maintient l'ordre
  • est POSIX

Exemple :

cat <<EOF > A
b
1
a
0
01
b
1
EOF

cat <<EOF > B
0
1
EOF

grep -Fvxf B A

Sortie :

b
a
01
b

Explication :

  • -F  :utilisez des chaînes littérales au lieu du BRE par défaut
  • -x  :ne prend en compte que les correspondances correspondant à la ligne entière
  • -v :impression non correspondante
  • -f file :prend les motifs du fichier donné

Cette méthode est plus lente sur les fichiers pré-triés que les autres méthodes, car elle est plus générale. Si la vitesse compte également, consultez :Un moyen rapide de trouver des lignes dans un fichier qui ne sont pas dans un autre ?

Voici une automatisation bash rapide pour un fonctionnement en ligne :

remove-lines() (
  remove_lines="$1"
  all_lines="$2"
  tmp_file="$(mktemp)"
  grep -Fvxf "$remove_lines" "$all_lines" > "$tmp_file"
  mv "$tmp_file" "$all_lines"
)

GitHub en amont.

utilisation :

remove-lines lines-to-remove remove-from-this-file

Voir aussi :https://unix.stackexchange.com/questions/28158/is-there-a-tool-to-get-the-lines-in-one-file-that-are-not-in-another


Linux
  1. Comment supprimer les lignes vides d'un fichier (y compris les tabulations et les espaces) ?

  2. Comment supprimer le Bom d'un fichier UTF-8 ?

  3. Comment supprimer des fichiers de la corbeille sur Ubuntu ?

  4. Comment supprimer les retours à la ligne d'un fichier texte ?

  5. Comment utiliser les lignes d'un fichier comme arguments d'une commande ?

Comment supprimer le mot de passe d'un fichier PDF sous Linux

Comment décompresser les fichiers gz sous Linux

Comment supprimer des lignes d'un fichier à l'aide de la commande Sed

Comment supprimer les caractères (^M) d'un fichier sous Linux

Comment supprimer des fichiers répertoriés dans un autre fichier sous Linux

Comment copier un fichier d'un autre répertoire vers celui en cours ?