bash подстановка и цитирование переменных - PullRequest
2 голосов
/ 10 февраля 2020

Возможно, это простой вопрос, но мне интересно, как кавычки работают с переменными. Кавычки вокруг значения переменной также вставляются для этой переменной? Например:

fred="\*"
echo $fred

приводит к выводу:

\*

Почему это так? Я бы подумал, что \* получит подпункт для $ fred, так что результат будет:

*

, но это не то, что происходит.

Ответы [ 2 ]

3 голосов
/ 10 февраля 2020

С bash Ручные расширения оболочки упорная шахта:

Порядок расширений: расширение скобки; расширение тильды, параметр и расширение переменной , арифметическое c расширение и подстановка команд (выполняется слева направо); расщепление слов; и расширение файла.

В системах, которые могут его поддерживать, доступно дополнительное расширение: замена процесса. Это выполняется одновременно с раскрытием тильды, параметра, переменной и арифметики c и заменой команды.

После выполнения этих расширений символы кавычек, присутствующие в исходном слове, удаляются, если они сами не были заключены в кавычки ( удаление кавычек ).

Затем удаление цитаты расширение - это то, что может заменить \* на *, выделение мое:

После предыдущих расширений все вхождения без кавычек символов '\', '' ' и '"' , которые не были получены в результате одного из приведенных выше расширений, удаляются .

Однако здесь происходит одно расширение (со значением) - расширение переменной. $fred вместо \* используется переменное расширение. Строка \* является результатом другого расширения, поэтому удаление кавычек не выполняется, поэтому оно остается в виде \*.

Делать кавычки вокруг значение переменной также вставляется в эту переменную?

№. $fred содержит два символа \*.

Почему это так?

\ не удаляется d, если это произошло в результате другого расширения.


Вас может заинтересовать расширение имени файла. Расширение имени файла происходит, когда , когда «слово» после расширения разделения слова «квалифицировано» для расширения имени файла. «Слово» квалифицируется для расширения имени файла, например, если есть символ *, который не находится в одинарных или двойных кавычках и не экранирован. * в \* экранируется символом backsla sh, поэтому * здесь не является «символом шаблона» ... В результате расширение имени файла не выполняется.

действительно ли происходит смещение в назначении?

Нет. "Globing" ie. расширение файла не выполняется при назначении переменной. Начиная с bash Параметры оболочки :

Переменная может быть назначена оператором вида

name=[value]

... Расширение имени файла не является выполнила. ...

Что самое интересное: вы можете запустить расширение имени файла с помощью трех слешей:

fred="\\\*"
touch '\file_with_backslash'
echo $fred  # will output `\file_with_backslash` 
            # and other files you have with leading backslash...

Итак fred="\\\*" значений \\* до fred (два \\ заменяется на один \). Затем в echo $fred, поскольку в \\ backsla sh экранируется от basksla sh, левый * не экранируется, поэтому он является символом шаблона, и слово соответствует расширению имени файла.

2 голосов
/ 10 февраля 2020

man bash раздел «цитирование» (мой акцент):

Заключение символов в двойные кавычки сохраняет буквальное значение всех символов в кавычках, за исключением $, `, \, и, когда расширение истории включено,! Когда оболочка находится в режиме posix, то! не имеет особого значения в двойных кавычках, даже если расширение истории включено. Символы $ и `сохраняют свое особое значение в двойных кавычках. Backsla sh сохраняет свое особое значение только тогда, когда за ним следует один из следующих символов: $, `,", \ или .

So backsla sh не экранирует каждый символ, в отличие от некоторых других языков.

...