I have a script that takes a MySQL SELECT query as its sole argument. Typically I enclose that query in single quotes and use double quotes within the query for enclosing the strings that are arguments of the query itself.

Occasionally this presents a problem, usually when the query itself must search for quote characters (single or double). I'm sure this can be resolved by properly escaping the single and double-quotes, but this is tricky since MySQL and the Linux shell may use different methods for escaping.

Example... here's an example, and it seems incredibly difficult to me... it needs to find single-quote characters that are preceded by a backslash. Note, this example does not intend to escape any characters for either MySQL or the CLI. The percent symbols act as wildcards in MySQL.

./show-results 'SELECT * FROM `table` WHERE `column` LIKE "%\'%"'

Is it possible to use something other than single or double-quotes to enclose a shell argument?

  • There exists in Bash an ANSI-C Quoting syntax $'whatever' with some designated escapes. Not sure how convenient that might be for the average user. It might be simpler to use a Here Document instead of a command arg, as this will be treated as data without expansions. – Paul_Pedant Sep 2 '20 at 21:26
  • and single quotes can be escaped in an ANSI-C string: echo $'don\'t do it'. But here documents avoid the leaning toothpick syndrome. – glenn jackman Sep 3 '20 at 1:34
  • Are you looking for a portable solution or are shell-specific alternatives fine as well? – fra-san Sep 3 '20 at 14:23
  • Also, and more importantly, does your use case involve interactively typing queries on the command line or writing them down as part of some script in which ./show-results is invoked? – fra-san Sep 3 '20 at 15:33

You did not provide a sample so I'm not sure if this will work for you.

Use here documents:

echo "$(cat <<'EOF'
foo "x" bar 'x'

When you run this with set -x you'll see that bash will escape this for you:

+ echo 'foo "x" bar '\''x'\'''
foo "x" bar 'x'

Now with your sample:

./show-results "$(cat <<'EOF'
SELECT * FROM `table` WHERE `column` LIKE "%\'%"

Results in the correct escaped arg:

./show-results 'SELECT * FROM `table` WHERE `column` LIKE "%\'\''%"'

The first backslash is inside '' so it is not acting as an escape and results in \, the second one is outside '' and is used to escape the single '.

  • And the heredoc labels must appear on their own lines like other languages? – Aaron Cicali Sep 3 '20 at 17:52
  • @AaronCicali Yes, the content of the here-document starts on the line that follows <<label and is terminated by a line containing only label. – fra-san Sep 3 '20 at 18:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.