Предположим, вы хотите добавить содержимое файла template
в файл data
только в том случае, если в data
уже нет строки из template
.
Команда для проверки того, найдена ли строка в template
в data
:
grep -xF -f template data
(Это разумно делать, только если template
содержит менее нескольких тысяч строк)
Здесь используются следующие опцииgrep
:
-x
, заставляя тестировать полные линии, от начала до конца строки. Без этого мы можем получить ложные срабатывания, если строка в template
совпадает со строкой в data
частично (, например, строка hello world
соответствует hello world!
частично ). -F
,с использованием сравнения строк, а не сопоставления регулярных выражений. Без этой опции grep
будет обрабатывать строки в template
как регулярные выражения, что может привести к неправильным результатам, если какая-либо строка шаблона содержит специальные символы в регулярных выражениях. -f template
, это заставляет grep
использовать каждую строку из template
отдельно в качестве шаблонов для сопоставления с каждой строкой в файле data
. Добавление опции -q
к этому (, чтобы сделать grep
тихим и позволить ему закрыться, как только будет найдено совпадение ), позволяет нам использовать его в простом тесте:
if ! grep -q -xF -f template data; then
cat template >>data
fi
Тело оператора if
добавляет файл template
в конец файла data
только в том случае, если команде grep
не удается найти совпадение каких-либо строк из template
в data
.
Встраивание {}
в шелл-код — всегда плохая идея, так как это приводит к уязвимости, связанной с внедрением команд. Всегда лучше передавать данные как отдельные аргументы (не -кода ).
Также -I
, без -d
/ -0
по-прежнему забивается кавычками и обратной косой чертой и удаляет ведущие пробелы. С GNU xargs
(, который вы должны использовать, поскольку вы уже используете -P
расширение GNU ), лучше всего использовать -d '\n'
для передачи каждой строки ввода в качестве отдельного аргумента
xargs -a txt -rd'\n' -P2 -n1 bash -c 'foo "$2" "$1"' bash "$a"
(вызывает один bash
вызов для каждой 1
строки ввода с содержимым $a
и текущей строки в качестве отдельных аргументов, которые упоминаются как $1
и $2
во встроенном сценарии оболочки ). ].
Или с-I
:
xargs -a txt -rd'\n' -P2 -I'{}' bash -c 'foo "$1" "$2"' bash {} "$a"
Здесь вы можете переключиться на zsh
, который имеет zargs
автозагружаемую функцию, которая может выполнять параллельную обработку а-ля GNU xargs
, включая функции без необходимости запускать отдельные вызовы оболочки или экспортировать функции, как это делает xargs
.
$ autoload zargs
$ foo() print -r - $1 is not $2
$ zargs -P2 -I {} {1..4} -- foo {} $a
1 is not foo
2 is not foo
3 is not foo
4 is not foo
С GNU Parallel это выглядит так:
foo() { echo "$1 is not $2"; }
export -f foo
seq 4 > txt
a=0
cat txt | parallel foo {} $a