1

Работая в оболочке (Unix), иногда мне нужно заключать в двойные кавычки или наоборот, то есть писать что-то вроде "foo 'bar baz' moo" или 'foo "bar baz" moo' . Это может быть потому, что

  • результирующая строка будет проанализирована снова (как с eval , с оболочкой, запущенной watch , с оболочкой, запущенной sshd на некотором удаленном сервере и т. д.), и эти внутренние кавычки имеют решающее значение для различения реальных аргументов во время этого второго анализа;
  • или мне просто нужен исходный аргумент для включения кавычек по любой другой причине.

Некоторая двусмысленность появляется, когда вместо bar baz меня есть переменная, скажем, $variable . Вот что говорит POSIX:

2.2.2. Одиночные кавычки

Заключение символов в одинарные кавычки ('') должно сохранять буквальное значение каждого символа в одинарных кавычках. Одиночная кавычка не может встречаться в одинарных кавычках.

2.2.3 Двойные кавычки

Заключение символов в двойные кавычки ("") должно сохранять буквальное значение всех символов в двойных кавычках, за исключением символов обратной кавычки, <знак доллара> и <обратный слэш>, следующим образом:

$
Они сохранят свое особое значение, представляя расширение параметров […], форму подстановки команд […] и арифметическое расширение […].

[...]

Не совсем очевидно, какое правило применяется для $variable внутри одинарных кавычек внутри двойных кавычек (или внутри двойных кавычек внутри одинарных кавычек), поэтому я спрашиваю:

  1. Какое правило относится к:

    • variable=123
      echo "'$variable'"
      
    • variable=123
      echo '"$variable"'
      

    (Я знаю, что на это можно легко ответить, просто попробовав, это будет разумное исследование. Я решил приложить эти усилия к ответу вики сообщества ниже).

  2. Есть ли исключения, причуды, сюрпризы?

    (Обратите внимание, что вики-ответ сообщества есть ниже. Вместо того, чтобы добавлять отдельный ответ с другим исключением или причудой, рассмотрите возможность добавления в сообщество вики).

1 ответ1

1

Какое правило применяется?

Просто пытаясь:

  • $ variable=123
    $ echo "'$variable'"
    '123'
    $
    
  • $ variable=123
    $ echo '"$variable"'
    "$variable"
    $
    

Так что внешние цитаты имеют значение. Обычные оболочки ведут себя одинаково: sh , bash , dash , zsh , ... Это из-за этого общего правила:

Если текущим символом является <обратная косая черта>, одинарная кавычка или двойная кавычка и он не заключен в кавычки, это влияет на цитирование для последующих символов до конца цитируемого текста.

(источник)

Только внешние кавычки не котируются, к ним применяется правило. Внутренние кавычки заключены в кавычки, они не влияют на последующие символы.


Есть ли исключения, причуды, сюрпризы?

(Ну, echo может преподнести несколько сюрпризов, см. Почему printf лучше, чем echo? Тем не менее, это отдельная проблема. Для удобства чтения ответ использует echo с безопасным значением $variable).

  1. Приведенный выше код дает нам либо '123' либо "$variable" . Что если нам понадобится "123" или '$variable'?

    • Чтобы получить "123":

      variable=123
      echo "\"$variable\""
      #     ^^         ^^   escaped inner quotes
      

      или же

      variable=123
      echo '"'"$variable"'"'
      #    1 12         23 3   outer quotes (numbered pairs)
      #     ^  ^^^^^^^^^  ^    quoted fragments
      
    • Чтобы получить '$variable':

      variable=123
      echo "'"'$variable'"'"
      #    1 12         23 3   outer quotes (numbered pairs)
      #     ^  ^^^^^^^^^  ^    quoted fragments
      
  2. Вопрос отмечает, что $ сохраняет свое особое значение в двойных кавычках. Это важно:

    На входные символы в строке в кавычках, которые также заключены между $( и соответствием ) , двойные кавычки не должны влиять, а скорее должны определять команду, вывод которой заменяет $(…) при раскрытии слова.

    (источник)

    Это означает, что кавычки в пределах $(…) должны рассматриваться независимо, несмотря на внешние двойные кавычки. В самом деле:

    $ variable=123
    $ echo "$(echo 'foo $variable')"
    $ #            ^             ^   single-quotes matter!
    foo $variable
    $
    

    (Обратите внимание, что echo $(stuff) - это плохой код в целом ; он здесь, чтобы проиллюстрировать текущую проблему).

    В этих двух случаях:

    • echo "'$variable'" (пробовал выше)
    • echo "$(echo 'foo $variable')" (обсуждается здесь)

    внутри одинарных кавычек внутри $variable , но $(…) сильно меняется. Аналогичная ситуация с echo "`echo 'foo $variable'`" (хотя $(…) и обратные метки не совсем эквивалентны).

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .