
В настоящее время я тестирую 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