Существует ли инструмент для получения строк в одном файле, которые не находятся в другом?

Можно хотеть использовать этот прием:

{ anycommand } | su -c 'tee file' user

tee(1) утилита POSIX, таким образом, можно полагаться на ее доступность.


Или, с sudo:

{ anycommand } | sudo -u user 'tee file'

111
27.08.2013, 21:34
8 ответов

Да. Стандарт grep инструмент для поиска файлов для текстовых строк может использоваться для вычитания всех строк в одном файле от другого.

grep -F -x -v -f fileB fileA

Это работает при помощи каждой строки в fileB как шаблон (-f fileB) и обработка его как простая строка для соответствия (не регулярный regex) (-F). Вы вынуждаете соответствие произойти на целой строке (-x) и распечатайте только строки, которые не соответствуют (-v). Поэтому Вы распечатываете строки в fileA, которые не содержат те же данные как никакая строка в fileB.

Оборотная сторона этого решения - то, что оно не принимает порядок строки во внимание и если Ваш вход имеет дублирующиеся строки в различных местах, Вы не могли бы получить то, что Вы ожидаете. Решение этого состоит в том, чтобы использовать реальный инструмент сравнения такой как diff. Вы могли сделать это путем создания различного файла со значением контекста в 100% строк в файле, затем парсинга его для просто строк, которые будут удалены при преобразовании файла A в файл B. (Обратите внимание, что эта команда также удаляет разность, форматирующую после того, как это получает правильные строки.)

diff -U $(wc -l < fileA) fileA fileB | sed -n 's/^-//p' > fileC
162
27.01.2020, 19:29
  • 1
    @inderpreet99 нижний регистр -u аргумент действительно на самом деле берет параметр числа, пока он не сопровождается пространством. Преимущество способа, которым у меня был он прежде, состоит в том, что это будет работать с или без значения, таким образом, Вы могли использовать что-то в этом, sub управляют стандартной программой, которая возвратила не вывод. Верхний регистр '-U', с другой стороны, требует аргумента. –  Caleb 28.08.2013, 00:46
  • 2
    быть осторожным, grep-f является O (N^2), я верю: stackoverflow.com/questions/4780203 / … –  rogerdpack 16.10.2015, 20:33
  • 3
    diff конвейерно обработайте работы, которые благодарит обработка. –  Felipe Alvarez 04.11.2016, 01:01
  • 4
    Для составления проблемы вида Вы могли использовать замену процесса в команде для обработки каждого файла перед grep по мере необходимости. Пример: grep -F -x -v -f <(sort fileB) <(sort fileA) –  Tony Cesaro 04.10.2017, 18:22
  • 5
    @TonyCesaro, Который работал бы, если Ваш набор данных не является конкретным порядком и дубликаты, не должен быть принят во внимание. Преимущество использования diff то положение в файле, принят во внимание. –  Caleb 05.10.2017, 09:06

Ответ зависит много от типа и формата файлов, которые Вы сравниваете.

Если файлы, которые Вы сравниваете, являются отсортированными текстовыми файлами, то инструмент GNU, записанный Richard Stallman и позвонившим Davide McKenzie comm может выполнить фильтрацию, Вы после. Это - часть coreutils.

Пример

Скажите, что у Вас есть следующие 2 файла:

$ cat a
1
2
3
4
5

$ cat b
1
2
3
4
5
6

Строки в файле b это не находится в файле a:

$ comm <(sort a) <(sort b) -3
    6
58
27.01.2020, 19:29
  • 1
    +1 для упоминания comm; к сожалению, comm требует отсортированных файлов –  Arcege 21.02.2012, 06:04
  • 2
    так сортирует их? коммуникация <(вид a) <(вид b)-1 - 2 –  Sirex 21.02.2012, 10:17
  • 3
    Это - некоторый странный синтаксис. <()? Это работает, и я получаю его, но есть ли название этой странности? –  mlissner 06.04.2017, 01:47
  • 4
    @mlissner <() также известен как замена процесса. –  miku 13.04.2017, 18:51
  • 5
    comm был первоначально записан приблизительно 1973 кем-то в Bell Labs, не RMS. Вы обращаетесь к реализации GNU, которая произошла намного позже. Было много различных реализаций утилит Unix через годы. –  Stéphane Chazelas 30.10.2017, 10:33

Вы могли также рассмотреть vimdiff, он выделяет различия между файлами в редакторе Vim

2
27.01.2020, 19:29
  • 1
    Но есть ли простой способ автоматически сделать вычитание в Vimdiff? –  Kazark 14.03.2013, 19:38

Если файлы являются большими, и у Вас нет пользовательского порядка к Вашим записям, grep берет слишком долго. Быстрая альтернатива была бы

sort file1 > 1 
sort file2 > 2 
diff 1 2 | grep "\>" | sed -e 's/> //'

[результаты file2-file1 для экранирования передайте по каналу в файл и т.д.]

Изменение > кому: < получил бы противоположное вычитание. rm 1 2

5
27.01.2020, 19:29

от stackoverflow...

коммуникация-23 file1 file2

- 23 подавляет строки, которые находятся в обоих файлах, или только в файле 2. Файлы должны быть отсортированы (они находятся в Вашем примере), но в противном случае передайте их по каналу через вид сначала...

См. страницу справочника здесь

32
27.01.2020, 19:29
  • 1
    , Это не работает на меня, по некоторым причинам... –  Jan 07.02.2018, 23:05
  • 2
    @Jan является Вашими отсортированными файлами? Как Вы сортировали их? –  JJS 08.02.2018, 21:03

grep и коммуникация (с видом) методы занимают много времени на больших файлах. SiegeX и ghostdog74 совместно использовали два замечательных awk метода для извлечения строк, уникальных для одного из двух файлов на Переполнении стека:

$ awk 'FNR==NR{a[$0]++}FNR!=NR && !a[$0]{print}' file1 file2

$ awk 'FNR==NR{a[$0]++;next}(!($0 in a))' file1 file2
8
27.01.2020, 19:29
  • 1
    Если Вы делаете это с огромными файлами, то ограничения памяти загрузки огромного файла в ассоциативный массив будут препятствующими. –  Charles Duffy 17.06.2016, 17:01

combineиз пакет moreutils интуитивно понятен:

combine fileA not fileB

Файлы не нужно сортировать, порядок сохраняется.

Существуют также операторы xor, orи and.

2
13.10.2020, 13:45
    awk 'NR==FNR{a[$1];next}!($1 in a){print }' fileA fileB

  

     cat fileA
    1
    2
    3
    4
    5
    6
    7
    8
    9
    
  file B
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
    
    output
    
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19


    It will print contents of fileB which is not in fileA
0
13.10.2020, 16:32

Теги

Похожие вопросы