Как избежать кавычек в оболочке?

66

У меня проблемы с экранированием символов в bash. Я хотел бы избежать одинарных и двойных кавычек при выполнении команды под другим пользователем. Для целей этого вопроса, скажем, я хочу отобразить следующее на экране:

'single quote phrase' "double quote phrase"

Как я могу избежать всех специальных символов, если мне также нужно переключиться на другого пользователя:

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

Конечно, это не дает правильного результата.

m33lky
источник
+1 за «Конечно, это не дает правильных результатов». bashна пути к тому, чтобы заставить меня злиться.
Рольф

Ответы:

89

Вы можете использовать следующий строковый литеральный синтаксис:

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

Из man bash

Слова вида $ 'string' обрабатываются специально. Слово расширяется до строки, символы с обратной косой чертой заменяются в соответствии со стандартом ANSI C. Escape-последовательности с обратной косой чертой, если они есть, декодируются следующим образом:

          \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
SiegeX
источник
5
Overkill. В большинстве случаев вам не нужно использовать строковый литерал синтаксиса.
fpmurphy
Более подробная информация здесь stackoverflow.com/a/16605140/149221
mj41
12

В оболочке POSIX, предполагая, что в вашей строке нет расширения переменной, команды или истории, а также нет новой строки, выполните следующие основные предписания:

  1. Чтобы заключить в обобщенную строку одинарные кавычки, выполните следующие действия:

    1. Замените любую последовательность символов, не входящих в одинарные кавычки, одинаковой последовательностью с добавленными начальными и конечными одинарными кавычками: 'aaa' ==> ''aaa''

    2. Избегайте обратной косой черты каждый существующий символ одинарной кавычки: ' ==> \'
      в частности,''aaa'' ==> \''aaa'\'

  2. Чтобы заключить в обобщенную строку двойные кавычки, выполните следующие действия:

    1. Добавьте ведущие и конечные двойные кавычки: aaa ==> "aaa"

    2. Escape с обратной косой чертой каждый символ двойной кавычки и каждый символ обратной косой черты: " ==> \", \ ==> \\

Пара примеров:

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

так что ваш пример может быть расширен следующим:

#!/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\\\"\""
enzotib
источник
10

Простой пример экранирования кавычек в оболочке:

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

Это сделано, заканчивая уже открытый one ( '), помещая экранированный one ( \'), затем открывая другой ( ').

В качестве альтернативы:

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

Это делается путем завершения уже открытой one ( '), размещения цитаты в другой quote ( "'"), а затем открытия другой ( ').

Связанный: Как избежать одиночных кавычек в одиночных кавычках? на стеке потока

kenorb
источник
1

Принятый ответ работает для простого (одноуровневого) цитирования:

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

Чтобы команда работала, вам нужно дважды заключить в кавычки.
Этот скрипт может сделать всю работу:

#!/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

Выполните скрипт, чтобы получить:

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

Первая строка работает для простого эха:

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

Вторая строка будет работать для команды с двойными кавычками:

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

источник
-3

эхо "я студент" не работает. Но работает следующее:

echo $ 'Я студент' Со страницы руководства bash:

Одиночная кавычка может отсутствовать между одинарными кавычками, даже если ей предшествует обратный слеш .... Слова вида $ 'string' обрабатываются специально. Слово расширяется до строки, символы с обратной косой чертой заменяются в соответствии со стандартом ANSI C.

Sarf
источник
6
Это ничего не добавляет к существующим ответам.
jasonwryan