В зависимости от конкретной ситуации, это либо явно не определено (так что реализации могут делать, как они будут), либо должно происходить так, как вы заметили. В вашем точном сценарии echo ab$, POSIX предписывает вывод «абы $» , что вы наблюдали и это не определенно . Краткое резюме всех различных случаев в конце.
Есть два элемента: сначала разбить на слова, а затем интерпретировать эти слова.
токенизации
Токенизация POSIX требует, чтобы a $не было началом действительного расширения параметра , подстановки команды или арифметической подстановки, чтобы считаться литеральной частью WORDсоздаваемого токена. Это связано с тем, что правило 5 («Если текущий символ не заключен в кавычки $или `, оболочка должна идентифицировать начало любых кандидатов на расширение параметра, замену команды или арифметическое расширение из их вводных последовательностей символов без кавычек: $или ${, $(или `, и $((, соответственно» ) не применяется, поскольку ни одно из этих расширений не является жизнеспособным. Расширение параметра требует, чтобы там отображалось действительное имя, а пустое имя недопустимо.
Поскольку это правило не применимо, мы продолжаем следовать, пока не найдем то, которое применимо. Два кандидата - № 8 («Если предыдущий символ был частью слова, текущий символ должен быть добавлен к этому слову.») И № 10 («Текущий символ используется в качестве начала нового слова».) , которые применяются к echo a$и echo $соответственно.
Существует также третий случай формы, echo a$+bкоторая проходит через ту же трещину, поскольку +это не имя специального параметра. К этому мы вернемся позже, так как он запускает разные части правил.
Таким образом, спецификация требует, чтобы $синтаксически она считалась частью слова, и затем она может быть дополнительно обработана.
Расширение слова
После того, как входные данные были проанализированы таким образом, с $включенным в слово, расширения слова применяются к каждому из прочитанных слов. Каждое слово обрабатывается индивидуально .
Указано, что :
Если после символа «без кавычек» следует символ, который не является одним из следующих:
- Числовой символ
- Имя одного из специальных параметров (см. Специальные параметры )
- Допустимый первый символ имени переменной
- A
<left-curly-bracket>('{')
-
<left-parenthesis>
результат не уточняется.
«Не указано» - это конкретный термин, означающий, что
- Соответствующая оболочка может выбрать любое поведение в этом случае
- Соответствующее приложение не может полагаться на какое-либо конкретное поведение
В вашем примере echo ab$, то $ не следует любому символ , так что это правило не применяется , и неопределенный результат не вызывается. Расширение $не вызывается, поэтому оно буквально присутствует и распечатывается.
Там , где она будет применяться в нашем третьем случае сверху: echo a$+b. Здесь $следует +, что не является число, специальный параметр ( @, *, #, ?, -, $, !, или 0), начало переменного имени (подчеркивания или буквенным от портативного набора символов ), или один из кронштейнов. В этом случае поведение не определено: соответствующая оболочка может изобрести специальный параметр, называемый +раскрытием , и соответствующее приложение не должно предполагать, что оболочка этого не делает . Оболочка может делать все что угодно, в том числе сообщать об ошибке.
Например, zsh, в том числе в своем режиме POSIX, интерпретируется $+bкак « bнабор переменных » и заменяет 1 или 0 вместо него. Он также имеет расширения для ~и =. Это соответствующее поведение.
Это может произойти и в другом месте echo "a$ b". Опять же, оболочке разрешено делать, как она хочет, и вы, как автор сценария, должны избегать $буквального вывода. Если нет, это может сработать, но вы не можете на это полагаться. Это абсолютная буква спецификации, но я не думаю, что такого рода детализация была задумана или рассмотрена.
В итоге
echo ab$: буквальный вывод, полностью указан
echo a$ b: буквальный вывод, полностью указан
echo a$ b$: буквальный вывод, полностью указан
echo a$b: расширение параметра b, полностью указано
echo a$-b: расширение специального параметра -, полностью указано
echo a$+b: неопределенное поведение
echo "a$ b": неопределенное поведение
В $конце слова вам разрешается полагаться на поведение, и оно должно рассматриваться буквально и передаваться echoкоманде как часть его аргумента. Это требование соответствия на оболочке.
$приобретает ли особое значение, если это последний символ в слове? Там нет единого специального значения, назначенного$; он используется для введения нескольких, но различных расширений, таких как расширение параметров${...}, подстановка команд$(...)и арифметические выражения$((...)). В некоторых оболочках вводятся дополнительные контексты, такие какkshвариант подстановки командx=${ echo foo; echo bar;}(который отличается от стандартного$(...)тем, что не выполняет команды в подоболочке).