2012-06-22 3 views
19

Хорошо, у меня есть два связанных списков на моем Linux поле в текстовых файлах:Bash - разница между двумя списками

/tmp/oldList 
/tmp/newList 

Мне нужно сравнить эти списки, чтобы увидеть, какие дополнительные линии и получили то, что линии были удалены. Затем мне нужно перебрать эти строки и выполнить действия над ними на основе того, были ли они добавлены или удалены. Как это сделать в bash?

+0

Тот же вопрос был задан за 4 дня до http://stackoverflow.com/questions/11099894/comparing-2-unsorted-lists-in-linux-listing-the-unique-in-the-second-file/11101143 # 11101143 –

ответ

50

Используйте команду comm(1) для сравнения двух файлов. Они оба должны быть отсортированы, что вы можете сделать заранее, если они большие, или вы можете сделать это inline с bash замещение процесса.

comm может принимать комбинацию флагов -1, -2 и -3, указывающих, какой файл для подавления строк из (уникальные в файл 1, уникальный в файл 2 или общие для обоих).

Чтобы получить строки только в старом файле:

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

Чтобы получить строки только в новом файле:

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

Вы можете кормить, что в петлю while read обработать каждую строку :

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

и аналогичным образом для новых линий.

4

diff command будет сравнивать вас.

например,

$ diff /tmp/oldList /tmp/newList 

См ссылку выше справочную страницу для получения дополнительной информации. Это должно позаботиться о вашей первой части вашей проблемы.

+1

Я просто хочу подчеркнуть, что команда 'diff' имеет смехотворное количество опций для форматирования вывода, что может обеспечить удобный вход в программу, которая будет обрабатывать различия. – chepner

+0

@chepner хорошая точка .. определенно стоит проверить связанную страницу man. – Levon

0

Вы пробовали diff

$ diff /tmp/oldList /tmp/newList 

$ man diff 
2

Рассмотрите возможность использования Ruby, если ваши скрипты требуют читаемости.

Чтобы получить строки только в старом файле:

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

Чтобы получить строки только в новом файле:

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

Вы можете кормить, что в то время чтения цикл для обработки каждого line:

while read old ; do 
    ...do stuff with $old 
done < ruby -e "puts File.readlines('/tmp/oldList') - File.readlines('/tmp/newList')" 
1

Это старый, но для полноты мы должны сказать, что если у вас действительно большой набор, то посты т решением будет использовать диф, чтобы создать сценарий, а затем источник его, как это:

#!/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 

Линии были изменены, будут отображаться как удаленные и добавил. Если вам это не нравится, вы можете использовать -changed-group-format. Проверьте справочную страницу diff.

Смежные вопросы