How to escape single quotes within single quoted strings


Question

Let's say, you have a Bash alias like:

alias rxvt='urxvt'

which works fine.

However:

alias rxvt='urxvt -fg '#111111' -bg '#111111''

won't work, and neither will:

alias rxvt='urxvt -fg \'#111111\' -bg \'#111111\''

So how do you end up matching up opening and closing quotes inside a string once you have escaped quotes?

alias rxvt='urxvt -fg'\''#111111'\'' -bg '\''#111111'\''

seems ungainly although it would represent the same string if you're allowed to concatenate them like that.

1
901
8/27/2019 1:34:14 PM

Accepted Answer

If you really want to use single quotes in the outermost layer, remember that you can glue both kinds of quotation. Example:

 alias rxvt='urxvt -fg '"'"'#111111'"'"' -bg '"'"'#111111'"'"
 #                     ^^^^^       ^^^^^     ^^^^^       ^^^^
 #                     12345       12345     12345       1234

Explanation of how '"'"' is interpreted as just ':

  1. ' End first quotation which uses single quotes.
  2. " Start second quotation, using double-quotes.
  3. ' Quoted character.
  4. " End second quotation, using double-quotes.
  5. ' Start third quotation, using single quotes.

If you do not place any whitespaces between (1) and (2), or between (4) and (5), the shell will interpret that string as a one long word.

1292
4/11/2016 6:34:24 PM

I always just replace each embedded single quote with the sequence: '\'' (that is: quote backslash quote quote) which closes the string, appends an escaped single quote and reopens the string.


I often whip up a "quotify" function in my Perl scripts to do this for me. The steps would be:

s/'/'\\''/g    # Handle each embedded quote
$_ = qq['$_']; # Surround result with single quotes.

This pretty much takes care of all cases.

Life gets more fun when you introduce eval into your shell-scripts. You essentially have to re-quotify everything again!

For example, create a Perl script called quotify containing the above statements:

#!/usr/bin/perl -pl
s/'/'\\''/g;
$_ = qq['$_'];

then use it to generate a correctly-quoted string:

$ quotify
urxvt -fg '#111111' -bg '#111111'

result:

'urxvt -fg '\''#111111'\'' -bg '\''#111111'\'''

which can then be copy/pasted into the alias command:

alias rxvt='urxvt -fg '\''#111111'\'' -bg '\''#111111'\'''

(If you need to insert the command into an eval, run the quotify again:

 $ quotify
 alias rxvt='urxvt -fg '\''#111111'\'' -bg '\''#111111'\'''

result:

'alias rxvt='\''urxvt -fg '\''\'\'''\''#111111'\''\'\'''\'' -bg '\''\'\'''\''#111111'\''\'\'''\'''\'''

which can be copy/pasted into an eval:

eval 'alias rxvt='\''urxvt -fg '\''\'\'''\''#111111'\''\'\'''\'' -bg '\''\'\'''\''#111111'\''\'\'''\'''\'''

Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Icon