
Atualmente estou testando o gnu paralelo para distribuir um comando de comparação em vários servidores usando o bash. Em sua função mais básica, este comando de comparação usa duas entradas para comparar (acessos ao banco de dados Oracle) e requer um nome de arquivo de saída via -o. Pelo menos uma ação carregar, salvar ou fazer upload direto é exigida pelo programa.
compare -o cmp.input1.input2.dat Input1 Input2
Eu tenho alguns milhares desses pares de entrada e crio um arquivo com todas as combinações para que cada linha contenha o nome do arquivo de saída e os identificadores do banco de dados exigidos pelo programa
#test_parallel
-o cmp.input1.input2.dat Input1 Input2
-o cmp.input1.input3.dat Input1 Input3
-o cmp.input2.input3.dat Input2 Input3
[...]
e execute o comando usando paralelo, porém o comando compare falha
parallel -a test_parallel "compare {}"
ERROR: No action specified for results (load, save or direct upload)
usage: compare [-u][-o <file>] query target
usando --dryrun
o modo, é isso que o paralelo executa:
compare -o\ cmp.input1.input2.dat\ Input1\ Input2
Por alguma razão que não entendo, o espaço em branco escapado não é tratado corretamente pelo programa de comparação. A execução deste comando no bash resulta exatamente na mesma mensagem de erro. Remover o escape após o sinalizador -o (eu poderia mover o -o para o comando paralelo) resulta em um erro de "muitos argumentos". A remoção de todos os escapes executa o comando conforme o esperado.
É possível dizer paralelo para não imprimir o escape na chamada de comando? Parece que não encontrei nada na documentação, exceto que este é o comportamento padrão esperado, conforme indicado porparallel --shellquote
Responder1
GNU Parallel trata a entrada como um único argumento e cita-a para que você possa usar nomes de arquivos com segurança como:
My brother's 12" records costs 30$ each.txt
No seu caso, você deseja que o argumento seja analisado pelo shell, para que os espaços não fiquem entre aspas:
parallel -a test_parallel eval compare {}
Ou você pode dividir no espaço:
parallel --colsep ' ' -a test_parallel compare {1} {2} {3} {4}
Mas como você deseja comparar tudo contra tudo, você pode fazer isso com muito mais elegância:
parallel cmp -o ../out/cmp.{1}.{2} {1} {2} ::: Input* ::: Input*
Isso comparará todas as entradas* com todas as entradas*. Com --results
você pode obter as saídas bem estruturadas em um diretório:
parallel --results out/ cmp {1} {2} ::: Input* ::: Input*
Mas se quiser pular a corrida cmp InputY InputX
depois de já ter corrido cmd InputX InputY
, você pode fazer o seguinte:
parallel --results out/ cmp {=1' $arg[1] ge $arg[2] and $job->skip();' =} {2} ::: Input* ::: Input*
Editar:
A versão 20190722 introduz a função uq
.
parallel -a test_parallel compare {=uq=}
uq
é uma função Perl. Quando chamado, o GNU Parallel evitará citar essa string de substituição. Assim, você pode misturar strings de substituição entre aspas e sem aspas:
parallel echo {} = {=uq=} ::: \$PWD
# You can change $_ if you want: uq() is a normal perl function
parallel echo {}ME = '{=uq(); $_.="ME"=}' ::: \$HO \$LOGNA