Bash-différence entre deux listes

Ok, j'ai deux listes connexes sur ma boîte linux dans des fichiers texte:

 /tmp/oldList
 /tmp/newList

je dois comparer ces listes pour voir quelles lignes ont été ajoutées et quelles lignes ont été supprimées. J'ai ensuite besoin de boucler ces lignes et d'effectuer des actions sur celles-ci selon qu'elles ont été ajoutées ou supprimées. Comment je fais ça à bash?

22
demandé sur Prince John Wesley 2012-06-23 02:56:39

5 réponses

comm(1) commande pour comparer les deux fichiers. Ils ont tous les deux besoin d'être triés, ce que vous pouvez faire à l'avance s'ils sont grands, ou vous pouvez le faire en ligne avec bash substitution de procédé.

comm peut prendre une combinaison des drapeaux -1,-2 et -3 indiquant le fichier à supprimer (unique au fichier 1, unique au fichier 2 ou commun aux deux).

Pour obtenir les lignes que dans l'ancien fichier:

comm -23 <(sort /tmp/oldList) <(sort /tmp/newList)

Pour obtenir de l' les lignes que dans le nouveau fichier:

comm -13 <(sort /tmp/oldList) <(sort /tmp/newList)

Vous pouvez nourrir que dans un while read boucle pour traiter chaque ligne:

while read old ; do
    ...do stuff with $old
done < <(comm -23 <(sort /tmp/oldList) <(sort /tmp/newList))

et de même pour les nouvelles lignes.

55
répondu camh 2012-06-23 00:08:40

commande diff fera la comparaison pour vous.

e.g.,

$ diff /tmp/oldList /tmp/newList

voir le lien de la page de manuel ci-dessus pour plus d'informations. Cela devrait prendre soin de votre première partie de votre problème.

5
répondu Levon 2012-06-22 22:58:51

envisagez D'utiliser Ruby si vos scripts ont besoin de lisibilité.

Pour obtenir les lignes que dans l'ancien fichier:

ruby -e "puts File.readlines('/tmp/oldList') - File.readlines('/tmp/newList')"

Pour obtenir les lignes que dans le nouveau fichier:

ruby -e "puts File.readlines('/tmp/newList') - File.readlines('/tmp/oldList')"

vous pouvez l'insérer dans une boucle de lecture pour traiter chaque ligne:

while read old ; do
  ...do stuff with $old
done < ruby -e "puts File.readlines('/tmp/oldList') - File.readlines('/tmp/newList')"
3
répondu Nowaker 2013-11-07 00:10:09

Ceci est ancien, mais pour être complet nous devrions dire que si vous avez un ensemble vraiment grand, la solution la plus rapide serait d'utiliser diff pour générer un script et ensuite le source, comme ceci:

#!/bin/bash

line_added() {
   # code to be run for all lines added
   # $* is the line 
}

line_removed() {
   # code to be run for all lines removed
   # $* is the line 
}

line_same() {
   # code to be run for all lines at are the same
   # $* is the line 
}

cat /tmp/oldList | sort >/tmp/oldList.sorted
cat /tmp/newList | sort >/tmp/newList.sorted

diff >/tmp/diff_script.sh \
    --new-line-format="line_added %L" \
    --old-line-format="line_removed %L" \
    --unchanged-line-format="line_same %L" \
    /tmp/oldList.sorted /tmp/newList.sorted

source /tmp/diff_script.sh

Les lignes modifiées apparaîtront comme supprimées et ajoutées. Si vous n'aimez pas cela, vous pouvez utiliser l'option --changé-groupe-format. Consultez la page de manuel diff.

1
répondu Costa Tsaousis 2015-02-03 19:57:39

Avez-vous essayé diff

$ diff /tmp/oldList /tmp/newList

$ man diff
0
répondu ssedano 2012-06-22 22:58:52