示例bash脚本
QRY="select * from mysql"
CMD="mysql -e \"$QRY\""
`$CMD`
我收到错误,因为*在我的CWD中被评估为glob(枚举)文件。
我看过其他帖子谈到引用" $ CMD"用于回声输出的参考,但在这种情况下
"$CMD"
将整个文字字符串抱怨为命令。
如果我
echo "$CMD"
然后将其复制/粘贴到命令行,似乎工作正常。
答案 0 :(得分:4)
你可以使用:
qry='select * from db'
mysql -e "$qry"
这不会受到*
shell的扩展。
如果您还要存储mysql
命令行,请使用BASH数组:
cmd=(mysql -e "$qry")
"${cmd[@]}"
答案 1 :(得分:1)
注意: anubhava's answer有正确的解决方案 这个答案提供了背景信息。
至于为什么你的方法不起作用:
"$CMD"
无法正常工作,因为bash将整个值视为单个令牌,并将其解释为命令名称,这显然会失败
`$CMD`
,即将$CMD
括在反引号中,在这种情况下是没有意义的(如果命令产生stdout输出 [1] ,则会产生意想不到的副作用);只使用:
$CMD
产生相同的 - 破坏 - 结果(只是更有效 - 通过封闭反引号,你不必要地创建一个子shell;使用反引号 - 或者更好,$(...)
只有在另一个中嵌入一个命令 - 见command substitution)。
$CMD
无效,
*
的无引号使用使其受到路径扩展(globbing) - 以及其他shell扩展。\
- 逃离水族字符。在执行字符串时,字符串会导致\
保留。虽然似乎,但您已将*
用双引号括起来(间接)放在转义双引号之间({{ 1}})在双引号字符串中, shell执行不查看这些转义双引号之间的内容,作为单个双引号字符串。
相反,这些双引号成为它们所邻接的标记的 literal 部分,而shell仍然在字符串上执行单词拆分(通过空格解析成单独的参数),和扩展,例如对生成的标记进行全球化。
如果我们假设关闭了globbing(通过\"$QRY\"
),那么当shell评估(未引用)set -f
时,传递给mysql
的参数的细分:
$CMD
- 所有剩余的参数都是无意中拆分的SQL命令。-e # $1
- 请注意"select # $2
已成为参数"
* # $3
from # $4
- 请注意mysql" # $5
已成为参数让您的解决方案使用现有的单字符串变量的唯一方法是使用"
,如下所示:
eval
这样,嵌入的转义双引号字符串被正确解析为单个双引号字符串(没有应用通配符),(在引用删除之后)作为单个参数传递给{{1} }。
但是,由于其安全隐患, eval "$CMD"
通常应避免(如果您不完全控制字符串的内容,则任意命令可以被执行)。
再次,请参考anubhava's answer以获得正确的解决方案。
[1]使用mysql
作为命令的注释:
它导致bash从eval
执行 stdout输出作为另一个命令,这很少是意图,并且通常会导致命令损坏,或者更糟糕的是,具有意想不到的效果的命令
尝试运行`$CMD`
(带反引号 - 与$CMD
相同);你得到`echo ha`
,因为bash试图执行命令输出 - $(echo ha)
- 作为命令失败。
功能