It looks like your command is maybe setting environment variables based on arguments given it on the command-line. It may be you can do:
CLUSTER=cl1; cluster=$CLUSTER command
...and set its environment for it at invocation.
Otherwise, shell quotes typically delimit arguments or escape other special shell characters from shell interpretation. You can contain (and therefore escape) different kinds of shell-quotes within other kinds based on various rules:
"''''"
- a soft-quoted string can contain any number of hard-quotes.
"\""
- a \
backslash can escape a "
soft-quote within a "
soft-quoted string.
- In this context a
\\
backslash also escapes itself, the \$
expansion token, and \n
ewlines as noted below, but is otherwise treated literally.
"${expand} and then some"
- a soft-quoted string can contain an interpreted shell $
expansion.
'"\'
- a '
hard-quoted string can contain any character other than a '
hard-quote.
\
- an unquoted backslash will escape any following character for literal interpretation - even another backslash - excepting a \n
ewline.
- In a
\\n
ewline case both the \
backslash and the \n
ewline are completely removed from the resulting interpreted command.
${parameter+expand "$parameter"}
- quotes resulting from a shell expansion almost never serve as delimiter markers excepting a few special cases. I won't venture to describe these further here.
I consider it odd that any application would interpret quotes in its command-line args. Such a practice doesn't make a lot of sense in that - for shells, at least - the primary purpose of a quote is generally to delimit an argument. At invocation, however, arguments are always already delimited with \0NUL
characters and so a quote cannot serve much purpose.
Even a shell will typically only bother to interpret quotes in one of its invocation arguments when it is called with a -c
switch - which denotes that its first operand is actually a shell script that it should run upon invocation. This is a case of twice evaluated input.
All that said, you can do a number of things to pass literal quotes via arguments on the command-line. For example:
CLUSTER='"cl1"'; command -p "cluster=$CLUSTER"
As I noted in a comment before, you can contain the "
quotes within an expansion that is itself "
quoted.
CLUSTER=cl1; command -p "cluster=\"$CLUSTER\""
You can escape the "
with a \
backslash within the "
quoted string.
CLUSTER=cl1; command -p cluster='"'"$CLUSTER"'"'
You can alternate and concatenate quoting styles to arrive at your desired end result as @jimmij notes above.
CLUSTER=cl1; ( set -f; IFS=; command -p cluster=\"$CLUSTER\" )
You can disable both file name generation and $IFS
splitting - thereby avoiding the need to quote the $expansion
at all - and so only quote the quotes. This is probably overkill.
Last, there is another type of shell-quote that might be used. As I noted before the sh -c "$scriptlet"
form of shell invocation is often used to provide a shell's script on the command-line. When $scriptlet
gets complicated though - such as when quotes must contain other quotes - it can often be advantageous to use a here-document and sh -s
instead - where the shell is specifically instructed to assign all following operands to the positional parameters as it would do in a -c
case and yet to also take its script from stdin
.
If your command must interpret quotes in this way then I would consider it better if it could do so in a file input. For example:
CLUSTER=cl1
command --stdin <<-SCRIPT
cluster="$CLUSTER"
SCRIPT
If you do not quote the delimiter of a <<here-document
then all of its contents are treated almost exactly like they were "
soft-quoted - except that "
double-quotes themselves are not treated specially. And so if we run the above with cat
instead:
CLUSTER=cl1
cat <<-SCRIPT
cluster="$CLUSTER"
SCRIPT
...it prints...
cluster="cl1"
In the example you mention, where the expansion for the alias is a single word containing no character that is subject to expansion, it makes no difference how you quote the name _cutf
:
$ alias cutf="_cutf"
$ alias cutf
alias cutf='_cutf'
$ unalias cutf
$ alias cutf='_cutf'
$ alias cutf
alias cutf='_cutf'
$ unalias cutf
$ alias cutf=_cutf
$ alias cutf
alias cutf='_cutf'
As you can see in that interaction, recalling the value of the alias cutf
gave the same result each time. So, yes, the quoting styles are interchangeable here.
It is not relevant that the expansion is to a function name: at least with bash, aliases perform a simple textual substitution (it is not obvious to me in what way defining an alias is useful; directly calling the underlying function seems just as easy).
Best Answer
A single-quoted string will retain the string as a literal. A double-quoted string will retain the string with variable interpolation and expansion. This is explained in the bash man page - see the section titled QUOTING