bash, Linux: установить разницу между двумя текстовыми файлами
у меня есть два файла A
-nodes_to_delete
и B
-nodes_to_keep
. Каждый файл имеет много строк с числовыми идентификаторами.
Я хочу иметь список числовых идентификаторов в nodes_to_delete
а не nodes_to_keep
, например, alt текст http://mathworld.wolfram.com/images/equations/SetDifference/Inline1.gif.
в базе данных PostgreSQL неоправданно медленно. Любой аккуратный способ сделать это в bash с помощью инструментов Linux CLI?
обновление: этот казалось бы, типичный для Python работа, но файлы очень большие. Я решил некоторые подобные проблемы с помощью uniq
,sort
и некоторые методы теории множеств. Это было примерно на два или три порядка быстрее, чем эквиваленты базы данных.
5 ответов:
The comm это.
кто-то показал мне, как именно это сделать в sh пару месяцев назад, а затем я не мог найти его некоторое время... и пока я смотрел, я наткнулся на ваш вопрос. Вот это :
set_union () { sort | uniq } set_difference () { sort | uniq -u } set_symmetric_difference() { sort | uniq -u }
использовать
comm
- он будет сравнивать два отсортированных файла строка за строкойответ на вопрос OP, используя этот пример настройки, появляется ниже. Эта команда вернет строки, уникальные для deleteNodes, а не в keepNodes
comm -1 -3 <(sort keepNodes) <(sort deleteNodes)
пояснение: показать строки, уникальные для deleteNodes, скрыть другие строки
пример настройки
мы будем использовать keepNodes и deleteNodes. Они используются как несортированные вход.
$ cat > keepNodes <(echo bob; echo amber;) $ cat > deleteNodes <(echo bob; echo ann;)
по умолчанию без аргументов comm печатает 3 столбца
unique_to_FILE1 unique_to_FILE2 lines_appear_in_both
это пример barebones
comm
без аргументов. Обратите внимание на три колонки.$ comm <(sort keepNodes) <(sort deleteNodes) amber ann bob
подавление вывода столбца
подавить столбец 1, 2 или 3 с помощью-N; обратите внимание, что когда столбец скрыт, пробелы сжимаются.
$ 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
он не будет изящно, когда вы забудете сортировать
comm: file 1 is not in sorted order
comm
был специально разработан для такого случая использования, но он требует отсортированного ввода.
awk
возможно, это лучший инструмент для этого, поскольку он довольно прямо вперед, чтобы найти разницу в наборе, не требуетsort
, и предлагает дополнительную гибкость.awk 'NR == FNR { a[]; next } !( in a)' nodes_to_keep nodes_to_delete
возможно, например, вы хотели бы найти только разницу в строках, которые представляют неотрицательные числа:
awk -v r='^[0-9]+$' 'NR == FNR && ~ r { a[] next } ~ r && !( in a)' nodes_to_keep nodes_to_delete
может быть, вам нужен лучший способ сделать это в postgres, я могу поспорить, что вы не найдете более быстрый способ сделать это с помощью плоских файлов. Вы должны быть в состоянии сделать простое внутреннее соединение и предполагая, что оба идентификатора cols индексируются, что должно быть очень быстро.