Распараллелить функцию, используя xargs и отдельные переменные

Распараллелить функцию, используя xargs и отдельные переменные

У меня есть текстовый файл из четырех строк с 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

Связанный контент