我从 bash shell 中执行带有星号的 MySQL 语句:
query=`cat <<EndOfMySQL
INSERT tmp_table
SELECT * FROM table
;
EndOfMySQL
`
echo $query
echo $query | mysql database
问题是星号被当前目录中的文件列表替换,查询变得错误。如何避免这种行为?无论我使用反引号还是$()
. 我希望有一些转义序列,例如\*
,但至少这个不起作用。
您可以通过引用分隔符字符串来防止此处文档中的参数扩展、命令替换和算术扩展:
... <<\EndOfMySQL
...
EndOfMySQL
转义单个字符也将阻止上面列出的扩展。
编辑:请注意,here-doc 的行不受文件名生成(通配符)的影响!
我想在这种情况下的问题是你没有引用传递给mysql的变量:
echo $query | mysql database
应该:
echo "$query" | mysql database
或者更好:
printf '%s\n' "$query" | mysql database
你为什么不使用:
query='INSERT into tmp_table
SELECT * FROM table;'
printf '%s\n' "$query" | mysql
或(如果您的 shell 支持here-strings,最新版本的bash支持它们):
mysql <<< "$query"
防止*
和其他 glob 字符扩展。禁用通配符——set -f
在您的Here Document之前使用
转义Here Document的分隔符的任何字符确实意味着执行No parameter expansion
, command substitution
, arithmetic expansion
, orpathname expansion
- 但是,pathname expansion
有一个警告!
从man bash
路径名扩展 — 分词后,* 除非-f
已设置该选项,否则 bash 会扫描每个单词中的字符 *、? 和 [。如果出现这些字符之一,则该词被视为一个模式,并替换为按字母排序的与该模式匹配的文件名列表。
Shell Builtin Commnds - set -f
- 禁用路径名扩展。
从help set
-f
– 禁用文件名生成(通配符)。如何将星号传递给 bash heredoc?
这样做没有诀窍——这里的文档带有星号可以正常工作。
这个问题是基于对症状的误解(这是一个容易犯的错误)。
星号的问题与 here-doc 或cat
. 期间*
扩展。echo $query
您可以通过替换cat
为tee temp.txt
和查看生成文件的内容来证明这一点。
但是,会处理其他类型的扩展(默认情况下),因此如果您确实想扩展星号,可以执行以下操作:
SELECT $(echo *) FROM table
您可以在 heredoc 的名称周围加上引号以完全禁用扩展:
cat <<'EndOfMySQL'