Your quoting is wrong. When you write $CMD
with no quotes, the value of $CMD
is broken up into “words” at each whitespace sequence¹ (the words can contain any non-whitespace character including punctuation), and then each word undergoes globbing (i.e. wildcard expansion). Note that quotes in the value of CMD
, in particular, are untouched: quotes have a meaning in the syntax of shell scripts but not in variable substitution. After this, the first word becomes the name of the command to execute, and subsequent words are the command's arguments.
In your example, assuming $KEYNAME
is somekeyname
and $HZID
is somehzid
, then the
command and arguments are:
./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
Note that text/xml;
appears as the first non-option argument; clearly the Perl script passes that argument down to curl
. The --
in the argument list is unrelated to your problem.
There's no way to stuff a command line into a variable. A (simple) variable is the wrong tool for that: it contains a string, but a command line is a list of strings (the command, and its arguments). You can stuff a command name and its argument into an array variable:
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[@]}")
The strange-looking syntax "${CMD[@]}"
expands the array variable CMD
to the list of words in the array. The double quotes prevent expansion of words inside the array, and [@]
is needed for historical reasons to tell the shell that you want to expand an array.
Another way to remember a command line, or an arbitrary shell snippet, for later use, is a function.
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)
¹ More precisely, according to the value of IFS
.
You should use like this:
"\"Test Internal Cluster\""
or wrap it in single quote
:
'"Test Internal Cluster"'
Test:
#!/bin/bash
echo $1
Output:
% bash test.sh "\"Test Internal Cluster\""
"Test Internal Cluster"
Update
The problem here is becasue you call perl
with $1
, $1
contains white space, so perl will see it as three separate arguments.
To prevent this, you should wrap $1
in double quotes "$1"
.
Another note is you should handle $1
argument in perl script, because if $1
contains any special characters, it will cause some bugs in perl program. you can use quotemeta($ARGV[0])
.
Note
I think you shoul not pass all argument as a string to shell script. You should pass them as normal, except cluster name, you still have to wrap it as string. Then pass them to perl script by "$@"
instead of $1
.
Best Answer
Using
grep
's-q
option is much more efficient than command substitution.The issue is single quotes (
'
) prevent shell variable expansion ($
). You need to use double quotes ("
).