Як уникнути цитат в оболонці?


65

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

'single quote phrase' "double quote phrase"

Як я можу уникнути всіх спеціальних символів, якщо мені також потрібно перейти на іншого користувача:

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

Звичайно, це не дає правильного результату.


+1 для "Звичайно, це не дає правильних результатів". bashдобре на шляху змусити мене злізти.
Рольф

Відповіді:


88

Ви можете використовувати такий синтаксис прямого рядка:

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

З man bash

Слова форми $ 'string "обробляються спеціально. Слово розширюється до рядка, а символи, що ухиляються від косої риски, замінюються відповідно до стандарту ANSI C. Послідовності втечі зворотного схилу, якщо вони є, декодуються наступним чином:

          \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

5
Перевищення. У більшості випадків вам не потрібно використовувати синтаксис рядкових літералів.
fpmurphy

Детальніше тут stackoverflow.com/a/16605140/149221
mj41

12

У оболонці POSIX, якщо припустити, що у вашому рядку немає змінної, розширення команд чи історії, і немає нового рядка, дотримуйтесь цих основних приписів:

  1. Щоб процитувати загальний рядок з одинарними лапками, виконайте такі дії:

    1. Замініть будь-яку послідовність символів, що не належать до однієї цитати, однаковою послідовністю з доданими провідними та кінцевими цитатами: 'aaa' ==> ''aaa''

    2. Уникнути за допомогою нахилу косою рисою кожного попереднього символу одиничної цитати: ' ==> \'
      Зокрема,''aaa'' ==> \''aaa'\'

  2. Щоб цитувати загальний рядок з подвійними лапками, виконайте такі дії:

    1. Додайте провідні та зворотні подвійні лапки: aaa ==> "aaa"

    2. Уникайте з косою рисою кожного подвійного символу цитати та кожного символу зворотної косої риси: " ==> \", \ ==> \\

Кілька прикладів:

''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\\\"\""

10

Простий приклад уникнення цитат у оболонці:

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

Це робиться, закінчивши вже відкритий один ( '), розмістивши втечене одне ( \'), потім відкривши ще одне ( ').

Як варіант:

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

Це робиться, закінчивши вже відкритий один ( '), помістивши цитату в іншу цитату ( "'"), потім відкривши ще одну ( ').

Пов’язано: Як уникнути одноцитат у рядах з цитатами з одним цитуванням? при stackoverflow SE


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 $ 'I \' ma student 'З чоловічої сторінки bash:

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


6
Це нічого не додає до існуючих відповідей.
Jasonwryan
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.