7

我从 bash shell 中执行带有星号的 MySQL 语句:

query=`cat <<EndOfMySQL
INSERT tmp_table
SELECT * FROM table
;
EndOfMySQL
`

echo $query

echo $query | mysql database

问题是星号被当前目录中的文件列表替换,查询变得错误。如何避免这种行为?无论我使用反引号还是$(). 我希望有一些转义序列,例如\*,但至少这个不起作用。

4

3 回答 3

6

您可以通过引用分隔符字符串来防止此处文档中的参数扩展、命令替换和算术扩展:

... <<\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"
于 2012-11-07T10:49:45.110 回答
2

防止*和其他 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– 禁用文件名生成(通配符)。
于 2015-05-28T23:18:32.813 回答
0

如何将星号传递给 bash heredoc?

这样做没有诀窍——这里的文档带有星号可以正常工作。

这个问题是基于对症状的误解(这是一个容易犯的错误)。

星号的问题与 here-doc 或cat. 期间*扩展。echo $query

您可以通过替换cattee temp.txt和查看生成文件的内容来证明这一点。


但是,会处理其他类型的扩展(默认情况下),因此如果您确实想扩展星号,可以执行以下操作:

SELECT $(echo *) FROM table

您可以在 heredoc 的名称周围加上引号以完全禁用扩展:

cat <<'EndOfMySQL'

另请参阅:如何将 heredoc 写入 Bash 脚本中的文件?

于 2020-06-29T00:30:39.710 回答