If you must store command fragments, use functions or arrays, not strings.
An example of best-practice code, in accordance with BashFAQ #50:
#!/usr/bin/env bash
bar=( --bar a="b" )
cmd=(foo "${bar[@]}" )
printf '%q ' "${cmd[@]}" && echo # print code equivalent to the command we're about to run
"${cmd[@]}" # actually run this code
Bonus: Your debug output doesn't prove what you think it does.
"a='b'"
and 'a='''b''''
are two different ways to quote the exact same string.
To prove this:
printf '%s
' "a='b'" | md5sum -
printf '%s
' 'a='''b'''' | md5sum -
...emits as output:
7f183df5823cf51ec42a3d4d913595d7 -
7f183df5823cf51ec42a3d4d913595d7 -
...so there's nothing at all different between how the arguments to echo $foo
and eval $foo
are being parsed in your code.
Why is this true? Because syntactic quotes aren't part of the command that's actually run; they're removed by the shell after it uses them to determine how to interpret a command line character-by-character.
So, let's break down what set -x
is showing you:
'a='''b''''
...consists of the following literal strings concatenated together:
a=
(in a single-quoted context that is entered and ended by the single quotes surrounding)
'
(in an unquoted context, escaped by the backslash that precedes it)
b
(in a single-quoted context that is entered and ended by the single quotes surrounding)
'
(in an unquoted context)
...everything else is syntactic, meaningful to the shell but not ever passed to the program foo
.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…