Escape a star (*) character in bash
I just cant do it. If * is in a variable, it expands to a list of files in current folder. echo "*" works fine.
#!/bin/bash
c="GRANT ALL ON \*.* TO '$1'@'localhost';"
mysql < $c
exit 0;
Solution 1:
Use single quotes for your string:
c='GRANT ALL ON *.* TO';
c="${c} '$1'@'localhost';";
There is probably a better way to do that but including $1 in the string made it weird
Solution 2:
Always put double quotes around variable substitutions, otherwise characters like spaces and
*
appearing in the value are interpreted by the shell. I.e., write"$c"
, not$c
.-
The syntax
mysql <"$c"
makesmysql
execute commands from a file whose name is the value of$c
. What you're looking for isprintf '%s\n' "$c" | mysql
or simpler, as long as you remember the restrictions (
$c
must not start with a-
, and if it contains\
that's ok in bash but not in some other variants of sh)echo "$c" | mysql
There's another alternative that's more comfortable if the command is multiline. It's called a “here-document”. The string
EOF
isn't special (though it's traditional), any sequence of letters and digits will do. The terminatingEOF
may not be preceded by whitespace. You need to put a\
before every$
,\
and`
unless you want them interpreted by the shell.mysql <<EOF GRANT ALL ON *.* TO '$1'@'localhost'; EOF
-
Beware that if the argument to the shell contains a single quote, you have an injection vector. The following snippet adds a
\
before every\
and'
.set -- "${1//\\/\\\\}" set -- "${1//\'/\'}"
This is fairly ugly, which is why if you're going to do anything complicated, forget about using a shell and use a language with actual SQL bindings (perl, python, whatever) where the library handles all the quoting and procedure building for you.