gnu paralelo elimina el escape antes de los caracteres de espacio en el comando

gnu paralelo elimina el escape antes de los caracteres de espacio en el comando

Actualmente estoy probando gnu paralelo para distribuir un comando de comparación en varios servidores usando bash. En su función más básica, este comando de comparación toma dos entradas para comparar (accesiones a bases de datos Oracle) y requiere un nombre de archivo de salida a través de -o. El programa requiere al menos una acción de carga, guardado o carga directa.

compare -o cmp.input1.input2.dat Input1 Input2

Tengo algunos miles de estos pares de entrada y creo un archivo con todas las combinaciones para que cada línea contenga el nombre del archivo de salida y los identificadores de la base de datos requeridos por el programa.

#test_parallel
-o cmp.input1.input2.dat Input1 Input2
-o cmp.input1.input3.dat Input1 Input3
-o cmp.input2.input3.dat Input2 Input3
[...]

y ejecutar el comando usando paralelo, sin embargo, el comando de comparación falla

parallel -a test_parallel "compare {}"
ERROR: No action specified for results (load, save or direct upload)
usage: compare [-u][-o <file>] query target

usando --dryrunel modo esto es lo que ejecuta paralelo:

compare -o\ cmp.input1.input2.dat\ Input1\ Input2

Por alguna razón que no entiendo, el programa de comparación no maneja correctamente el espacio en blanco escapado. La ejecución de este comando en bash da como resultado exactamente el mismo mensaje de error. Eliminar el escape después del indicador -o (podría mover -o al comando paralelo) genera un error de "demasiados argumentos". Al eliminar todos los escapes se ejecuta el comando como se esperaba.

¿Es posible decirle a paralelo que no imprima el escape en la llamada de comando? Parece que no encuentro nada en la documentación, excepto que este es el comportamiento predeterminado esperado, como lo indicaparallel --shellquote

Respuesta1

GNU Parallel trata la entrada como un argumento único y la cita para que puedas usar nombres de archivos de forma segura como:

My brother's 12" records costs 30$ each.txt

En su caso, desea que el shell analice el argumento, por lo que los espacios no estarán entre comillas:

parallel -a test_parallel eval compare {}

O puedes dividir en el espacio:

parallel --colsep ' ' -a test_parallel compare {1} {2} {3} {4}

Pero como quieres comparar todo versus todo, puedes hacerlo de manera mucho más elegante:

parallel cmp -o ../out/cmp.{1}.{2} {1} {2} ::: Input* ::: Input*

Esto comparará todas las entradas* con todas las entradas*. Con --resultsusted puede obtener los resultados bien estructurados en un directorio:

parallel --results out/ cmp {1} {2} ::: Input* ::: Input*

Pero si desea omitir la ejecución cmp InputY InputXdespués de haberla ejecutado cmd InputX InputY, puede hacer esto:

parallel --results out/ cmp {=1' $arg[1] ge $arg[2] and $job->skip();' =} {2} ::: Input* ::: Input*

Editar:

La versión 20190722 introduce la función uq.

parallel -a test_parallel compare {=uq=}

uqes una función de Perl. Cuando se le llame, GNU Parallel se abstendrá de citar esa cadena de reemplazo. Así que puedes mezclar cadenas de reemplazo entre comillas y sin comillas:

parallel echo {} = {=uq=} ::: \$PWD
# You can change $_ if you want: uq() is a normal perl function
parallel echo {}ME = '{=uq(); $_.="ME"=}' ::: \$HO \$LOGNA

información relacionada