简体   繁体   English

如何将星号传递给 bash heredoc?

[英]How to pass an asterisk into bash heredoc?

I execute a MySQL statement with an asterisk from within a bash shell:我从 bash shell 中执行带有星号的 MySQL 语句:

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

echo $query

echo $query | mysql database

The problem is that the asterisk is replaced by the list of files in the current directory and the query becomes erroneous.问题是星号被当前目录中的文件列表替换,查询变得错误。 How to avoid this behavior?如何避免这种行为? It doesn't matter whether I use backticks or $() .使用反引号还是$()都没有关系。 I'd expect some escape sequence like \* , but at least this one doesn't work.我希望有一些像\*这样的转义序列,但至少这个是行不通的。

You could prevent parameter expansion, command substitution, and arithmetic expansion in a here-document by quoting the delimiter string:您可以通过引用分隔符字符串来防止此处文档中的参数扩展、命令替换和算术扩展:

... <<\EndOfMySQL
...
EndOfMySQL

Escaping the single character will also prevent the expansions listed above.转义单个字符也会阻止上面列出的扩展。

Edit: Note that the lines of the here-doc are no subject to filename generation (globbing)!编辑:请注意,here-doc 的行不受文件名生成(通配)的约束!

I suppose that the problem in this case is that you didn't quote the variable passed to mysql :我想这种情况下的问题是你没有引用传递给mysql的变量:

echo $query | mysql database

should be:应该:

echo "$query" | mysql database

or better yet:或者更好:

printf '%s\n' "$query" | mysql database

Why don't you use:你为什么不使用:

query='INSERT into tmp_table
SELECT * FROM table;'
printf '%s\n' "$query" | mysql

or (if your shell supports here-strings , recent versions of bash support them):或者(如果你的 shell 支持here-strings ,最新版本的bash支持它们):

mysql <<< "$query"

To prevent * and other glob charcters from expanding.防止*和其他 glob 字符扩展。 disable globbing –use set -f before your Here Document禁用globbing——在你的Here Document之前使用set -f

Escaping any of the characters of the delimiter of Here Document does mean that No parameter expansion , command substitution , arithmetic expansion , or pathname expansion is performed – However, pathname expansion has a caveat !转义Here Document定界符的任何字符确实意味着不执行parameter expansioncommand substitutionarithmetic expansionpathname expansion ——但是, pathname expansion有一个警告

From man bash来自man bash

  • Pathname Expansion — After word splitting, *unless the -f option has been set, bash scans each word for the characters *, ?, and [.路径名扩展——分词后,*除非设置了-f选项,bash 会扫描每个词中的字符 *、? 和 [。 If one of these characters appears, then the word is regarded as a pattern, and replaced with an alphabetically sorted list of file names matching the pattern.如果出现这些字符之一,则该词被视为一种模式,并替换为按字母顺序排列的与该模式匹配的文件名列表。

  • Shell Builtin Commnds — set -f – Disable pathname expansion. Shell 内置命令 — set -f – 禁用路径名扩展。

From help set来自help set

  • -f – Disable file name generation (globbing). -f – 禁用文件名生成(通配)。

How to pass an asterisk into bash heredoc?如何将星号传递给 bash heredoc?

There is no trick to doing this -- the here document works fine with an asterisk.这样做没有什么诀窍——这里的文档在带星号的情况下效果很好。

This question is based on a misinterpretation of the symptoms (which is an easy mistake to make here).这个问题是基于对症状的误解(这是一个很容易犯的错误)。

The issue with the asterisk has nothing to do with the here-doc or the execution of cat .星号的问题与 here-doc 或cat的执行无关。 The * is expanded during echo $query . *echo $query期间扩展。

You could prove this to yourself by replacing cat with tee temp.txt , and reviewing the contents of the generated file.您可以通过将cat替换为tee temp.txt并查看生成文件的内容来向自己证明这一点。


However, other types of expansion are processed (by default), so if you did want to expand the asterisk, you could do something like this:但是,处理其他类型的扩展(默认情况下),因此如果您确实想扩展星号,您可以这样做:

SELECT $(echo *) FROM table

You can put quotes around the name of the heredoc to disable expansion altogether:您可以在 heredoc 的名称周围加上引号以完全禁用扩展:

cat <<'EndOfMySQL'

See also: How can I write a heredoc to a file in Bash script?另请参阅:如何将 heredoc 写入 Bash 脚本中的文件?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM