146

I'm having trouble with escaping characters in bash. I'd like to escape single and double quotes while running a command under a different user. For the purposes of this question let's say I want to echo the following on the screen:

'single quote phrase' "double quote phrase"

How can I escape all the special chars, if I also need to switch to a different user:

sudo su USER -c "echo \"'single quote phrase' \"double quote phrase\"\""

Of course, this doesn't produce the right result.

1
  • 2
    ... except it DOES work as expected, you have to escape quotes 2 times since your string is nested within other string. It would work the same in any other programming language: bash -c "echo \"'single quote phrase' \\\"double quote phrase\\\"\""
    – ptixed
    Nov 11, 2020 at 19:12

5 Answers 5

187

You can use the following string literal syntax:

> echo $'\'single quote phrase\' "double quote phrase"'
'single quote phrase' "double quote phrase"

From man bash

Words of the form $'string' are treated specially. The word expands to string, with backslash-escaped characters replaced as specified by the ANSI C standard. Backslash escape sequences, if present, are decoded as follows:

          \a     alert (bell)
          \b     backspace
          \e
          \E     an escape character
          \f     form feed
          \n     new line
          \r     carriage return
          \t     horizontal tab
          \v     vertical tab
          \\     backslash
          \'     single quote
          \"     double quote
          \nnn   the eight-bit character whose value is the octal value nnn (one to three digits)
          \xHH   the eight-bit character whose value is the hexadecimal value HH (one or two hex digits)
          \cx    a control-x character
3
  • 2
    More details here stackoverflow.com/a/16605140/149221
    – mj41
    Apr 28, 2018 at 13:18
  • Just a note to others if the "From man bash" doesn't clue you in, this will not work on sh even though that's how the question was [mis?]tagged.
    – Hashbrown
    Sep 7 at 13:48
  • @Hashbrown good catch, fixed.
    – SiegeX
    Sep 8 at 14:57
46

Simple example of escaping quotes in shell:

$ echo 'abc'\''abc'
abc'abc
$ echo "abc"\""abc"
abc"abc

It's done by finishing already opened one ('), placing escaped one (\'), then opening another one (').

Alternatively:

$ echo 'abc'"'"'abc'
abc'abc
$ echo "abc"'"'"abc"
abc"abc

It's done by finishing already opened one ('), placing quote in another quote ("'"), then opening another one (').

Related: How to escape single-quotes within single-quoted strings? at stackoverflow SE

0
17

In a POSIX shell, assuming in your string there is no variable, command or history expansion, and there is no newline, follow these basic prescriptions:

  1. To quote a generic string with single quotes, perform the following actions:

    1. Substitute any sequence of non-single-quote characters with the same sequence with added leading and trailing single quotes: 'aaa' ==> ''aaa''

    2. Escape with a backslash every preexisting single quote character: ' ==> \'
      In particular, ''aaa'' ==> \''aaa'\'

  2. To quote a generic string with double quotes, perform the following actions:

    1. Add leading and trailing double quotes: aaa ==> "aaa"

    2. Escape with a backslash every double quote character and every backslash character: " ==> \", \ ==> \\

A couple of examples:

''aaa""bbb''ccc\\ddd''  ==>  \'\''aaa""bbb'\'\''ccc\\ddd'\'\'
                        ==>  "''aaa\"\"bbb''ccc\\\\ddd''"

so that you example could be expanded with the following:

#!/bin/sh

echo \''aaa'\'' "bbb"'
echo "'aaa' \"bbb\""

sudo su enzotib -c 'echo \'\'\''aaa'\''\'\'\'' "bbb"'\'
sudo su enzotib -c 'echo "'\''aaa'\'' \"bbb\""'

sudo su enzotib -c "echo \\''aaa'\\'' \"bbb\"'"
sudo su enzotib -c "echo \"'aaa' \\\"bbb\\\"\""
13

The accepted answer works for simple (one level) quoting:

$ echo $'\'single quote phrase\' "double quote phrase"'
'single quote phrase' "double quote phrase"

To get the command presented to work, you need to quote twice.
This script could do all the work:

#!/bin/bash

quote () { 
    local quoted=${1//\'/\'\\\'\'};
    printf "'%s'" "$quoted"
}

read -r line <<-\_line_to_quote_
'single quote phrase' "double quote phrase"
_line_to_quote_

quote "$line"; echo
quote "echo $(quote "$line")"; echo

Execute the script to get:

$ script
''\''single quote phrase'\'' "double quote phrase"'
'echo '\'''\''\'\'''\''single quote phrase'\''\'\'''\'' "double quote phrase"'\'''

The first line works for simple echo:

$ echo ''\''single quote phrase'\'' "double quote phrase"'
'single quote phrase' "double quote phrase"

The second line will work for the double quoted command:

sudo su USER -c 'echo '\'''\''\'\'''\''single quote phrase'\''\'\'''\'' "double quote phrase"'\'''
1
  • 1
    This quote function is amazing! It can be used in scripts to do arbitrarily deep quoting without being exponentially uglier. e.g. eval "eval $(quote "eval $(quote "eval $(quote "echo test")")")" Sep 14, 2020 at 15:33
1

Simple

Remove double quotes by piping your output to sed

sed 's/"//g'

Example

somethingThatProducesDoubleQuotesHere | removeDoubleQuotes

Or you could use a method to make life easier in the future

removeDoubleQuotes() {
  sed 's/"//g'
  # EXAMPLES:
  # somethingThatProducesDoubleQuotesHere | removeDoubleQuotes
}

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .