我有一个脚本,它生成一个 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 脚本之后嵌入的参数发生了一些情况:
卷曲:(6)无法解析主机“文本”
但是,我可以获取我回显的确切命令,并从 shell 提示符运行它,并且脚本可以正确运行。似乎当我使用 RESULT= 与 backtic 运行它时,$CMD
参数没有通过“Content-Type: etc...”周围的双引号传递。
我正在运行的命令是这个(仅更改了键名和主机 ID 参数)
./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 脚本处理的,但我不清楚为什么要传递它。这是因为绕过位置参数处理吗?该脚本是为处理 3 种不同的用例而编写的。我认为这不相关,但为了完整起见,该脚本用于调用 AWS 的 Route 53 Rest api。
答案1
你的引用是错误的。当您$CMD
不使用引号写入时, 的值$CMD
会在每个空白序列处被分解为“单词”(单词可以包含任何非空白字符,包括标点符号),然后每个单词都会进行通配符扩展(即通配符扩展)。请注意,值中的引号CMD
尤其保持不变:引号在 shell 脚本的语法中有意义,但在变量替换中没有意义。此后,第一个单词成为要执行的命令的名称,后续单词是命令的参数。
在您的示例中,假设$KEYNAME
issomekeyname
和$HZID
is somehzid
,则命令和参数为:
./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
.参数列表中的--
与您的问题无关。
无法将命令行填充到变量中。 (简单)变量是错误的工具:它包含一个字符串,但命令行是字符串列表(命令及其参数)。您可以将命令名称及其参数填充到数组变量中:
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
到数组中的单词列表。双引号可防止数组内的单词扩展,并且[@]
由于历史原因需要双引号来告诉 shell 您要扩展数组。
记住命令行或任意 shell 片段以供以后使用的另一种方法是函数。
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
。