линии GREP, которые существуют на одном файле, но не в другом

Опции в fstab должны использоваться для перемонтирования, применяя указанные опции (которые НЕ могут включать rw доступ). Загрузочный скрипт, который жестко запрограммирован на перемонтирование корневого фс с rw без обращения к fstab, сломан. Таким образом, единственным результатом исключения этого параметра из fstab будет то, что он не будет перемонтирован и останется ro без применения других опций.

4
08.07.2018, 19:21
8 ответов

Предположим, что все файлы отсортированы и что мы используем оболочку, которая понимает подстановки процессов (, напримерbash):

$ join -t. -v 1 -o 0 <( join -t. a.txt b.txt ) c.txt
c

или, для других оболочек,

$ join -t. a.txt b.txt | join -t. -v 1 -o 0 - c.txt
c

Дважды используется joinдля выполнения реляционных соединений между файлами. Данные интерпретируются как разделенные точками -поля (с-t.).

Соединение между a.txtи b.txtявляется прямым и дает

a.up
b.up
c.up

Это все строки из двух файлов, в которых первое поле, разделенное точкой -, встречается в обоих файлах. Выходные данные состоят из поля соединения (a, b, c), за которым следуют другие поля из обоих файлов (только b.txtимеет дополнительные данные ).

Второе соединение немного более особенное. С -v 1мы просим просмотреть записи в первом файле (промежуточный результат выше ), который не может быть сопряжен ни с одной строкой во втором файле, c.txt. Кроме того, мы просим показать только само поле соединения (-o 0). Без флага -oв результате мы получили бы c.up.


Если файлы не отсортированы, то каждое вхождение имени файла fileможет быть заменено на <( sort file )в команде.

3
27.01.2020, 20:47

Одной быстрой командой GNUawk:

awk -F'.' \
'{
     if (ARGIND == 1) a[$1];
     else if (ARGIND == 2 && $1 in a) comm[$1];
     else if (ARGIND == 3){
         delete a;
         if ($1 in comm) delete comm[$1]
     }
 }
 END{ for (i in comm) print i }' a.txt b.txt c.txt

Выход:

c

  • -F'.'-рассматривать .как разделитель полей
  • ARGIND-Индекс вARGV(массиве аргументов командной строки )текущего обрабатываемого файла
  • comm-массив из общих элементов между первыми двумя файлами(a.txtиb.txt)
4
27.01.2020, 20:47

Вот еще один вариант использования, похожий на ваш, с использованием :grep, sort& uniqи sed.

$ sed 's/\.\(dw\|up\)//' up.txt dw.txt | grep -xFf a.txt | sort | uniq -u
c

Это работает путем создания списка совпадений для каждого из файлов up.txtи dw.txt, используя a.txtв качестве входного файла для grep. Это дает такой вывод:

$ sed 's/\.\(dw\|up\)//' up.txt dw.txt | grep -xFf a.txt
a
b
c
a
b

Ключевыми деталями здесь являются то, что мы:

  • использование sedдля удаления всех конечных расширений из двух файлов up.txtиdw.txt
  • После удаления расширений мы используем grepдля фильтрации любых соответствующих совпадений изa.txt
  • Сопоставление, которое мы приказываем grepвыполнить, является точным,-x
  • -Fуказывает grepобрабатывать шаблоны в a.txtкак фиксированные строки

Имея приведенный выше вывод, вы можете просто запустить его через sort, а затем использовать uniq, чтобы получить только те строки, которые не повторяются.

Ссылки

0
27.01.2020, 20:47

связь

Предполагая, что файлы отсортированы и повторяющиеся строки удалены:

comm -12 a.txt <(cut -d. -f1 b.txt) | comm -23 - <(cut -d. -f1 c.txt)

Это написано для Ubuntu с использованием утилит Bash и GNU, но, надеюсь, оно работает и для других ОС.

Пояснение

  • comm -12Распечатайте строки, общие для обоих файлов (читайте man commдля подробностей)
  • <(...)Замена процесса -Использовать команду вместо входного файла
  • cut -d. -f1В каждой строке удалить все после первой точки
  • comm -23Печатать строки, уникальные для первого файла
  • -Чтение из стандартного ввода вместо файла
2
27.01.2020, 20:47

Вариация ответа Романа и упрощение:

gawk -F. 'ARGIND==1{ seen[$1]; next } 
         ARGIND==2{ delete seen[$1]; next }
         ($1 in seen)
' fileUP fileDW fileA
  • Этот ARGIND==1{ seen[$1]; next }содержит первый столбец fileUP в ассоциированном массиве с именем seen.
  • Это ARGIND==2{ delete seen[$1]; next }удаляет те, которые существуют в fileDW .
  • и это ($1 in seen)печатает оставшиеся единицы, когда они также существуют в файле A
0
27.01.2020, 20:47
$ grep -f a.txt <(cut -d '.' -f 1 up.txt) > common.txt
$ grep -vf <(cut -d '.' -f 1 dw.txt) common.txt

Сравнивает первое слово между двумя файлами и записывает соответствующее слово в common.txt. Сравнивает dw.txtс common.txtи выводит обратное совпадение, т.е. 'с'.

0
27.01.2020, 20:47
perl -F\\. -lane '
   $h{@ARGV}{$F[0]}++,next if @ARGV;
   print if exists $h{2}{$_} && !exists $h{1}{$_};
' up.txt dw.txt a.txt

Создайте хеш %h с ключами верхнего уровня как "2" и "1", где 2 относится к первому аргументу (up.txt ), 1 относится к dw.txt. Для приведенных данных хэш-структура будет выглядеть примерно так :(порядок может отличаться)

%h = (
   1 => { a => 1, b => 1, },
   2 => { a => 1, b => 1, c => 1, },
);

как видно, внутри основного хеша %h есть два мини-хэша -. Поэтому, когда приходит время читать третий аргумент (a.txt ), мы принимаем решение распечатать запись, основываясь на том, можно ли увидеть эту запись (как ключ )в мини -хэш %2 И не отображается в мини-хэше -%1, внутри основного хэша %h (, также называемом хэшем -из -хэшей, или HoH ).

0
27.01.2020, 20:47

Если указанные файлы отсортированы и нет внутренних дубликатов, используйте это:

$ comm -12 a.txt <(sed 's/\.[^.]*$//' up.txt) | comm -23 - <(sed 's/\.[^.]*$//' dw.txt)

В оболочках с заменой процессов(<(…)). О других оболочках читайте ниже.


То, что вы описываете в этом предложении:

get the lines from a.txt that exists in b.txt and not in c.txt

можно было бы свести к операциям над множествами:

( a intersect b ) complement c

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

Мне нравится, как команда commможет выполнять большинство операций.
Но файлы, которые вы представляете, не являются чистым набором для использования. Расширения нужно стереть/удалить. Общий способ удаления расширений с помощью sed:

$ sed 's/\.[^.]*$//' file

Итак, два чистых файла будут созданы с:

$ sed 's/\.[^.]*$//' up.txt > up.txt.clean
$ sed 's/\.[^.]*$//' dw.txt > dw.txt.clean

С этими двумя файлами решение с одним -вкладышем:

$ comm -12 a.txt up.txt.clean | comm -23 - dw.txt.clean
c

Или, делая( up.txt complement dw.txt) intersect a.txt:

$ comm -23 up.txt.clean dw.txt.clean | comm -12 - a.txt
c

Обе команды могут быть реализованы непосредственно из исходных файлов в некоторых оболочках с:

$ comm -12 a.txt <(sed 's/\.[^.]*$//' up.txt) | comm -23 - <(sed 's/\.[^.]*$//' dw.txt)

Если подстановка процесса недоступна, можно использовать только один файл следующим образом:

$ sed 's/\.[^.]*$//' up.txt | comm -12 a.txt - >result1.txt
$ sed 's/\.[^.]*$//' dw.txt | comm -23 result1.txt -
c
$ rm result1.txt
2
27.01.2020, 20:47

Теги

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