Опции в fstab должны использоваться для перемонтирования, применяя указанные опции (которые НЕ могут включать rw доступ). Загрузочный скрипт, который жестко запрограммирован на перемонтирование корневого фс с rw без обращения к fstab, сломан. Таким образом, единственным результатом исключения этого параметра из fstab будет то, что он не будет перемонтирован и останется ro без применения других опций.
Предположим, что все файлы отсортированы и что мы используем оболочку, которая понимает подстановки процессов (, например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 )
в команде.
Одной быстрой командой 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
)Вот еще один вариант использования, похожий на ваш, с использованием :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
, чтобы получить только те строки, которые не повторяются.
Предполагая, что файлы отсортированы и повторяющиеся строки удалены:
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
Печатать строки, уникальные для первого файла -
Чтение из стандартного ввода вместо файла Вариация ответа Романа и упрощение:
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$ 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
и выводит обратное совпадение, т.е. 'с'.
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 ).
Если указанные файлы отсортированы и нет внутренних дубликатов, используйте это:
$ 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