gnu parallel удалить escape перед символами пробела в команде

gnu parallel удалить escape перед символами пробела в команде

В настоящее время я тестирую gnu parallel для распределения команды сравнения по нескольким серверам с помощью bash. В своей самой базовой функции эта команда сравнения принимает два входных данных для сравнения (доступы к базе данных Oracle) и требует имя выходного файла через -o. Для программы требуется по крайней мере одно действие: загрузка, сохранение или прямая загрузка.

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

У меня есть несколько тысяч таких входных пар, и я создаю файл со всеми комбинациями, так что каждая строка содержит имя выходного файла и идентификаторы базы данных, необходимые программе.

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

и выполнить команду с помощью parallel, однако команда compare не выполняется

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

используя --dryrunрежим, вот что выполняет parallel:

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

По какой-то непонятной мне причине экранированный пробел не обрабатывается правильно программой сравнения. Выполнение этой команды в bash приводит к точно такому же сообщению об ошибке. Удаление экранирования после флага -o (я мог бы переместить -o в параллельную команду) приводит к ошибке "слишком много аргументов". Удаление всех экранирований выполняет команду так, как и ожидалось.

Можно ли указать parallel не печатать escape при вызове команды? Я, кажется, ничего не нашел в документации, кроме того, что это ожидаемое поведение по умолчанию, как указано вparallel --shellquote

решение1

GNU Parallel обрабатывает входные данные как один аргумент и заключает их в кавычки, поэтому вы можете безопасно использовать такие имена файлов, как:

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

В вашем случае вы хотите, чтобы аргумент был проанализирован оболочкой, поэтому пробелы будут сняты с кавычек:

parallel -a test_parallel eval compare {}

Или вы можете разделить по пространству:

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

Но поскольку вы хотите сравнить все со всеми, вы можете сделать это гораздо элегантнее:

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

Это сравнит все Input* со всеми Input*. С помощью --resultsвы можете получить выходные данные, хорошо структурированные в каталоге:

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

Но если вы хотите пропустить бег cmp InputY InputXпосле того, как вы уже пробежали cmd InputX InputY, то вы можете сделать следующее:

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

Редактировать:

В версии 20190722 представлена ​​функция uq.

parallel -a test_parallel compare {=uq=}

uqявляется функцией perl. При вызове GNU Parallel воздержится от кавычек этой строки замены. Таким образом, вы можете смешивать строки замены в кавычках и без кавычек:

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

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