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 54

5 ответов:

кто-то показал мне, как именно это сделать в 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 индексируются, что должно быть очень быстро.