How can I escape double quotes inside a double string in Bash?
For example, in my shell script
#!/bin/bash dbload="load data local infile \"'gfpoint.csv'\" into table $dbtable FIELDS TERMINATED BY ',' ENCLOSED BY '\"' LINES TERMINATED BY \"'\n'\" IGNORE 1 LINES" I can't get the ENCLOSED BY '\"' with double quote to escape correctly. I can't use single quotes for my variable, because I want to use variable $dbtable.
9 Answers
Use a backslash:
echo "\"" # Prints one " character. 3A simple example of escaping quotes in the shell:
$ echo 'abc'\''abc' abc'abc $ echo "abc"\""abc" abc"abc It's done by finishing an already-opened one ('), placing the escaped one (\'), and then opening another one (').
Alternatively:
$ echo 'abc'"'"'abc' abc'abc $ echo "abc"'"'"abc" abc"abc It's done by finishing already opened one ('), placing a quote in another quote ("'"), and then opening another one (').
More examples: Escaping single-quotes within single-quoted strings
3Keep in mind that you can avoid escaping by using ASCII codes of the characters you need to echo.
Example:
echo -e "This is \x22\x27\x22\x27\x22text\x22\x27\x22\x27\x22" This is "'"'"text"'"'" \x22 is the ASCII code (in hex) for double quotes and \x27 for single quotes. Similarly you can echo any character.
I suppose if we try to echo the above string with backslashes, we will need a messy two rows backslashed echo... :)
For variable assignment this is the equivalent:
a=$'This is \x22text\x22' echo "$a" # Output: This is "text" If the variable is already set by another program, you can still apply double/single quotes with sed or similar tools.
Example:
b="Just another text here" echo "$b" Just another text here sed 's/text/"'\0'"/' <<<"$b" #\0 is a special sed operator Just another "0" here #this is not what i wanted to be sed 's/text/\x22\x27\0\x27\x22/' <<<"$b" Just another "'text'" here #now we are talking. You would normally need a dozen of backslashes to achieve the same result in the normal way. 2Bash allows you to place strings adjacently, and they'll just end up being glued together.
So this:
echo "Hello"', world!' produces
Hello, world! The trick is to alternate between single and double-quoted strings as required. Unfortunately, it quickly gets very messy. For example:
echo "I like to use" '"double quotes"' "sometimes" produces
I like to use "double quotes" sometimes In your example, I would do it something like this:
dbtable=example dbload='load data local infile "'"'gfpoint.csv'"'" into '"table $dbtable FIELDS TERMINATED BY ',' ENCLOSED BY '"'"'"' LINES "'TERMINATED BY "'"'\n'"'" IGNORE 1 LINES' echo $dbload which produces the following output:
load data local infile "'gfpoint.csv'" into table example FIELDS TERMINATED BY ',' ENCLOSED BY '"' LINES TERMINATED BY "'\n'" IGNORE 1 LINES It's difficult to see what's going on here, but I can annotate it using Unicode quotes. The following won't work in Bash – it's just for illustration:
dbload=‘load data local infile "’“'gfpoint.csv'”‘" into ’“table $dbtable FIELDS TERMINATED BY ',' ENCLOSED BY '”‘"’“' LINES ”‘TERMINATED BY "’“'\n'”‘" IGNORE 1 LINES’
The quotes like “ ‘ ’ ” in the above will be interpreted by bash. The quotes like " ' will end up in the resulting variable.
If I give the same treatment to the earlier example, it looks like this:
echo “I like to use” ‘"double quotes"’ “sometimes”
Store the double quote character in a variable:
dqt='"' echo "Double quotes ${dqt}X${dqt} inside a double quoted string" Output:
Double quotes "X" inside a double quoted string 2Check out printf...
#!/bin/bash mystr="say \"hi\"" Without using printf
echo -e $mystr Output: say "hi"
Using printf
echo -e $(printf '%q' $mystr) Output: say \"hi\"
3Make use of $"string".
In this example, it would be,
dbload=$"load data local infile \"'gfpoint.csv'\" into table $dbtable FIELDS TERMINATED BY ',' ENCLOSED BY '\"' LINES TERMINATED BY \"'\n'\" IGNORE 1 LINES" Note (from the man page):
1A double-quoted string preceded by a dollar sign ($"string") will cause the string to be translated according to the current locale. If the current locale is C or POSIX, the dollar sign is ignored. If the string is translated and replaced, the replacement is double-quoted.
For use with variables that might contain spaces in you Bash script, use triple quotes inside the main quote, e.g.:
[ "$(date -r """$touchfile""" +%Y%m%d)" -eq "$(date +%Y%m%d)" ] Add "\" before double quote to escape it, instead of \
#! /bin/csh -f set dbtable = balabala set dbload = "load data local infile "\""'gfpoint.csv'"\"" into table $dbtable FIELDS TERMINATED BY ',' ENCLOSED BY '"\""' LINES TERMINATED BY "\""'\n'"\"" IGNORE 1 LINES" echo $dbload # load data local infile "'gfpoint.csv'" into table balabala FIELDS TERMINATED BY ',' ENCLOSED BY '"' LINES TERMINATED BY "''" IGNORE 1 LINES 1