bash, Linux: Définir la différence entre deux fichiers texte

J’ai deux fichiers Anodes_to_delete et Bnodes_to_keep . Chaque fichier a plusieurs lignes avec des identifiants numériques.

Je veux avoir la liste des identifiants numériques qui sont dans nodes_to_delete mais PAS dans nodes_to_keep , par exemple alt text http://soffr.miximages.com/bash/Inline1.gif .

Le faire dans une firebase database PostgreSQL est excessivement lent. Un bon moyen de le faire en bash en utilisant les outils de la CLI Linux?

UPDATE: Cela semble être un travail Pythonic, mais les fichiers sont vraiment très volumineux. J’ai résolu des problèmes similaires en utilisant l’ uniq , le sort et certaines techniques de théorie des ensembles. C’était environ deux ou trois fois plus rapide que les équivalents de la firebase database.

La commande comm le fait.

Quelqu’un m’a montré comment faire exactement cela en sh il y a quelques mois, et puis je ne pouvais pas le trouver pendant un moment … et en regardant je suis tombé sur votre question. C’est ici :

 set_union () { sort $1 $2 | uniq } set_difference () { sort $1 $2 $2 | uniq -u } set_symmesortingc_difference() { sort $1 $2 | uniq -u } 

utilisez comm – il comparera deux fichiers sortingés ligne par ligne

La réponse à la question de OP en utilisant cet exemple de configuration apparaît ci-dessous. Cette commande renverra des lignes uniques à deleteNodes, pas dans keepNodes

 comm -1 -3 <(sort keepNodes) <(sort deleteNodes) 

explication: affiche les lignes uniques à deleteNodes, cache les autres lignes


exemple d'installation

Nous utiliserons keepNodes et deleteNodes. Ils sont utilisés comme entrée non sortingée.

 $ cat > keepNodes <(echo bob; echo amber;) $ cat > deleteNodes <(echo bob; echo ann;) 

Par défaut sans arguments, comm imprime 3 colonnes

 unique_to_FILE1 unique_to_FILE2 lines_appear_in_both 

Ceci est un exemple de comm sans arguments. Notez les trois colonnes.

 $ comm <(sort keepNodes) <(sort deleteNodes) amber ann bob 

Suppression de la sortie de colonne

Supprimer la colonne 1, 2 ou 3 avec -N; Notez que lorsqu'une colonne est masquée, l'espace blanc diminue.

 $ comm -1 <(sort keepNodes) <(sort deleteNodes) ann bob $ comm -2 <(sort keepNodes) <(sort deleteNodes) amber bob $ comm -3 <(sort keepNodes) <(sort deleteNodes) amber ann $ comm -1 -3 <(sort keepNodes) <(sort deleteNodes) ann $ comm -2 -3 <(sort keepNodes) <(sort deleteNodes) amber $ comm -1 -2 <(sort keepNodes) <(sort deleteNodes) bob 

Il échouera gracieusement lorsque vous oubliez de sortinger

comm: file 1 is not in sorted order

comm été spécifiquement conçue pour ce type de cas d’utilisation, mais nécessite des entrées sortingées.

awk est sans doute un meilleur outil pour cela, car il est assez simple de trouver une différence, ne nécessite pas de sort et offre une flexibilité supplémentaire.

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

Vous voudrez peut-être, par exemple, ne trouver que la différence de lignes représentant des nombres non négatifs:

 awk -vr='^[0-9]+$' 'NR == FNR && $0 ~ r { a[$0] next } $0 ~ r && !($0 in a)' nodes_to_keep nodes_to_delete 

Peut-être que vous avez besoin d’une meilleure façon de le faire dans postgres, je peux très bien parier que vous ne trouverez pas un moyen plus rapide de le faire en utilisant des fichiers plats. Vous devriez être capable de faire une simple jointure interne en supposant que les deux identifiants sont indexés, ce qui devrait être très rapide.