
У меня есть текстовый файл из четырех строк с 1, 2, 3 и 4 в каждой. Также у меня есть функция, которую я хочу распараллелить:foo() { echo "$1 is not $2"; }
Я экспортирую функцию:export -f foo
Теперь я хочу вызвать функцию с параметрами из текстовых файлов, используя xargs
для распараллеливания.ИЯ также хочу использовать переменную ( a=0
) как параметр в функции. Поэтому я бы вызвал функцию так:cat txt | xargs -I "{}" -P 2 bash -c 'foo {} $a'
НОэто игнорирует переменную ( a=0
). И выводит:
«1 не есть»… «4 не есть» и т. д.
Если я вызываю: cat txt | xargs -I "{}" -P 2 bash -c 'foo {} 0'
это работает и я получаю правильный вывод
"1 не0" ... "4 не0" и т. д
Но мне нужно вызвать его, используя переменную ( a=0
), а не ноль. Как это сделать?
решение1
Встраивание {}
в код оболочки всегда плохая идея, поскольку это приводит к уязвимости инъекции команд. Всегда лучше передавать данные как отдельные (не кодовые) аргументы.
Также -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
решение2
С GNU Parallel это выглядит так:
foo() { echo "$1 is not $2"; }
export -f foo
seq 4 > txt
a=0
cat txt | parallel foo {} $a