Вызов сценария из bash имеет проблему с аргументами

У меня есть сценарий, который генерирует XML-файл, а затем выполняет скрипт perl, передавая ему ряд аргументов. Вот код ключа:

CMD="./dnscurl.pl --keyname $KEYNAME -- -X POST -H \"Content-Type: text/xml; charset=UTF-8\" --upload-file /tmp/file.xml https://route53.amazonaws.com/2010-10-01/hostedzone/$HZID/rrset" echo "Executing..." echo $CMD RESULT=`$CMD` 

Когда это выполняется, результат указывает, что что-то происходит со встроенными аргументами после того, как параметр -H отправлен в сценарий dnscurl.pl:

curl: (6) Не удалось разрешить текст хоста

Тем не менее, я могу взять точную команду, которую я выбрал, и запустить ее из командной строки, и скрипт работает правильно. Кажется, что когда я запускаю его с помощью backtic, используя RESULT = $CMD параметры не передаются с двойными кавычками вокруг «Content-Type: etc …».

Команда, которую я запускаю, является этой (изменены только параметры keyname и hostid)

 ./dnscurl.pl --keyname mykey -- -X POST -H "Content-Type: text/xml; charset=UTF-8" --upload-file /tmp/file.xml https://route53.amazonaws.com/2010-10-01/hostedzone/ZZZZZZZ/rrset 

Единственное, что мне интересно, это использование «-», которое они передают. Я понимаю, что это специфично для обработки сценариев dnscurl.pl, но я не понимаю, почему это передается. Это связано с тем, что вы занимаетесь обработкой позиционных аргументов? Сценарий был написан для обработки трех разных вариантов использования. Я не думаю, что это актуально, но только для полноты, этот скрипт используется для совершения звонков на маршрут 53 AWS.

Ваше цитирование неверно. Когда вы пишете $CMD без кавычек, значение $CMD разбивается на «слова» в каждой пробельной последовательности¹ (слова могут содержать любой символ без пробелов, включая пунктуацию), а затем каждое слово подвергается глобальному расширению (например, расширение подстановки) , Обратите внимание, что цитаты в значении CMD , в частности, не затронуты: цитаты имеют смысл в синтаксисе скриптов оболочки, но не в замене переменных. После этого первое слово становится именем исполняемой команды, а последующие слова являются аргументами команды.

В вашем примере, предполагая, что $KEYNAME – это somekeyname а $HZIDsomehzid , тогда команда и аргументы:

 ./dnscurl.pl --keyname $KEYNAME -- -X POST -H "Content-Type: text/xml; charset=UTF-8" --upload-file /tmp/file.xml https://route53.amazonaws.com/2010-10-01/hostedzone/somehzid/rrset 

Обратите внимание, что text/xml; появляется как первый аргумент без опционов; очевидно, что Perl-скрипт передает этот аргумент до curl . Список аргументов не связан с вашей проблемой.

Невозможно набить командную строку в переменную. A (простая) переменная является неправильным инструментом для этого: она содержит строку, но командная строка представляет собой список строк (команда и ее аргументы). Вы можете записать имя команды и ее аргумент в переменную массива:

 CMD=(./dnscurl.pl --keyname "$KEYNAME" -- -X POST -H "Content-Type: text/xml; charset=UTF-8" --upload-file /tmp/file.xml "https://route53.amazonaws.com/2010-10-01/hostedzone/$HZID/rrset") RESULT=$("${CMD[@]}") 

Странно выглядящий синтаксис "${CMD[@]}" расширяет переменную массива CMD до списка слов в массиве. Двойные кавычки предотвращают расширение слов внутри массива, а для исторических причин требуется [@] сообщить оболочке, что вы хотите расширить массив.

Другим способом запоминания командной строки или произвольного фрагмента оболочки для последующего использования является функция.

 cmd () { ./dnscurl.pl --keyname "$KEYNAME" -- \ -X POST -H "Content-Type: text/xml; charset=UTF-8" \ --upload-file /tmp/file.xml \ "https://route53.amazonaws.com/2010-10-01/hostedzone/$HZID/rrset" } RESULT=$(cmd) 

¹ Более точно, согласно значению IFS .