#bash #parallel-processing
#bash #параллельная обработка
Вопрос:
Я пишу параллельную команду в bash, и мне нужно указать элемент массива, индекс которого изменяется в зависимости от номера задания параллельного выполнения задания, в качестве аргумента.
Я пытался использовать переменную $PARALLEL_SEQ, но я не могу заставить синтаксис работать.
#!/usr/bin/env bash
test_array=(apple orange lemon mango banana)
seq 5 | parallel echo ${test_array[$PARALLEL_SEQ]}
Я ожидаю, что второй аргумент после parallel будет вычислен со строкой в результате (например, ‘orange’ для второго параллельного выполнения).
Я хочу, чтобы мой код печатался:
apple
orange
lemon
mango
banana
и не:
apple 1
apple 2
apple 3
apple 4
apple 5
Ответ №1:
из вашей команды PARALLEL_SEQ расширяется th shell перед вызовом parallel.
из документации
Однако, если вы хотите использовать переменную оболочки, вам нужно заключить знак $ в кавычки. Вот пример использования $PARALLEL_SEQ . Эта переменная устанавливается самой GNU parallel, поэтому вычисление $ должно выполняться вспомогательной оболочкой, запущенной GNU parallel:
seq 10 | parallel -N2 echo seq:$PARALLEL_SEQ arg1:{1} arg2:{2}
После комментария я смог найти cygwin с parallel и мог протестировать следующие команды, которые сработали:
foo(){ test_array=(apple orange lemon mango banana);}
export -f foo
seq 5 | parallel 'foo amp;amp; echo "${test_array[PARALLEL_SEQ-1]}" amp;amp; : '
обходной путь из-за невозможности экспорта массивов через среду
:
в конце находится команда no-op, поэтому последний аргумент, переданный parallel, не принимается в качестве аргумента для команды echo.
Комментарии:
1. Я не вижу, как это может решить мою проблему с выводом правильного значения из массива. Не могли бы вы уточнить, как я могу добиться желаемого результата? Обратите внимание, что порядок печатных элементов может отличаться, поскольку команды выполняются параллельно. Заранее спасибо.
2. я не смог протестировать, потому что у меня нет среды с установленным parallel, но вам, возможно, придется экспортировать массив (или, может быть, просто использовать его напрямую, потому что подоболочка может видеть неэкспортированные переменные), но вам нужно выполнить escape
$
, чтобы предотвратить расширение текущей оболочки до того, как parallel сможет их увидеть. Может быть, просто используя одинарные кавычкиecho '${test_array[$PARALLEL_SEQ]}'
Ответ №2:
env_parallel
сделано для вас:
# Ignore all variables set now
env_parallel --start
# Introduce a new variable
test_array=(apple orange lemon mango banana)
# Copy that variable to the environment of the command
seq 5 | env_parallel echo '${test_array[{= $_=seq() -1 =}]}'
Он работает даже на удаленных системах:
# Copy that variable to the environment of the command on the remote server
seq 5 | env_parallel -S server echo '${test_array[{= $_=seq() -1 =}]}'
Однако для этого вам понадобится довольно новая версия GNU Parallel.