
Eu tenho um arquivo de texto de quatro linhas com 1, 2, 3 e 4 em cada linha. Além disso, tenho uma função que desejo paralelizar:foo() { echo "$1 is not $2"; }
Eu exporto a função:export -f foo
Agora quero chamar a função com parâmetros dos arquivos de texto usados xargs
para paralelizar.ETambém quero usar uma variável ( a=0
) como parâmetro na função. Então, eu chamaria a função como:cat txt | xargs -I "{}" -P 2 bash -c 'foo {} $a'
MASisso ignora a variável ( a=0
). E saídas:
"1 não é" ... "4 não é" etc.
Se eu ligar: cat txt | xargs -I "{}" -P 2 bash -c 'foo {} 0'
funciona e obtenho a saída correta
"1 não é0" ... "4 não é0" etc.
Mas preciso chamá-lo usando a variável ( a=0
) e não usando zero. Como eu posso fazer isso?
Responder1
Incorporar o {}
código shell é sempre uma má ideia, pois introduz uma vulnerabilidade de injeção de comando. É sempre melhor passar dados como argumentos separados (sem código).
Além disso -I
, sem -d
/ -0
ainda engasga com aspas, barras invertidas e faixas em branco. Com o GNU xargs
(que você deve usar porque já está usando a -P
extensão GNU), o melhor é usar -d '\n'
para passar cada linha de entrada como argumento separado
xargs -a txt -rd'\n' -P2 -n1 bash -c 'foo "$2" "$1"' bash "$a"
(chama uma bash
invocação para cada 1
linha da entrada com o conteúdo $a
e a linha atual como argumentos separados que são referidos como $1
e $2
no script shell embutido).
Ou com -I
:
xargs -a txt -rd'\n' -P2 -I'{}' bash -c 'foo "$1" "$2"' bash {} "$a"
Aqui você pode mudar para zsh
qual possui uma zargs
função autocarregável que pode fazer processamento paralelo à la GNU xargs
, inclusive de funções sem ter que executar invocações de shell separadas ou exportar funções como xargs
faz.
$ 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
Responder2
Com o GNU Parallel fica assim:
foo() { echo "$1 is not $2"; }
export -f foo
seq 4 > txt
a=0
cat txt | parallel foo {} $a