
В ksh на старом компьютере Solaris я использовал:
export PS1="$PWD $"
чтобы установить приглашение на текущий каталог. Это работает отлично, пока вы не сделаете cd в другом месте, тогда вы увидите, что он не оценивает PWD каждый раз. Я заметил, что это исправляется установкой PS1 следующим образом:
export PS1="\$PWD $"
Просто интересно, как это называется, как работает, есть ли другие приложения и т. д. (Это одна из тех вещей, которые довольно трудно найти в Google.)
решение1
Несколько фрагментов документации помогут это объяснить.
ИзДокумент стандартов POSIX для оболочки:
Следующие переменные влияют на выполнение оболочки:
PS1: Каждый раз, когда интерактивная оболочка готова прочитать команду, значение этой переменной должно быть подвергнуто расширению параметров и записано в стандартный поток ошибок.
...
Одинарные кавычки
Заключение символов в одинарные кавычки должно сохранять буквальное значение каждого символа внутри одинарных кавычек.
...
Двойные кавычки
Заключение символов в двойные кавычки должно сохранять буквальное значение всех символов внутри двойных кавычек, за исключением
$: Знак доллара должен сохранять свое особое значение, вводя расширение параметров
...
Символ экранирования (обратная косая черта)
Обратная косая черта, не заключенная в кавычки, должна сохранять буквальное значение следующего символа.
Итак, значение PS1
подлежит расширению параметра, и это то, что вам нужно, поэтому оно $PWD
будет оцениваться каждый раз, когда вы получаете приглашение. Это означает, что $PWD
в значении должна быть фактическая строка PS1
. Но,
PS1="$PWD $ "
установит значениеPWD
во время выполнения оператора присваиванияв PS1
. PS1
будет что-то вроде /home/poldie $
, и это никогда не изменится после этого. Вы этого не хотите.
PS1="\$PWD $ "
Обратная косая черта заключает в кавычки $
, так что это PS1
содержит буквальную строку $PWD $
. Вам это нужно.
PS1='$PWD $ '
сделает то же самое. Параметры не раскрываются, если заключены в одинарные кавычки.
(Примечание: изначально все это было у меня в виде export
операторов, потому что автор решил написать их в виде export
операторов. @Kusalananda удалил их. Не знаю, почему. Экспорт PS1 — допустимый выбор, если вы хотите, чтобы дочерние оболочки (например, созданные командой :sh
в vi) сохраняли ваше пользовательское приглашение.)
решение2
Символ \
экранирует следующий (специальный) символ. В этом случае он экранирует $
, который мы обычно используем для разыменования переменной. Когда оболочка оценивает назначение переменной, она сначала расширяет правую часть выражения. Без перед \
, $PWD
оболочка расширяет $PWD
и присваивает результат PS1
.
Однако с \
, оболочка обрабатывает $PWD
как литеральную строку и присваивает ее как есть PS1
, так что PS1
содержит строку $PWD
, а не развернутое значение переменной $PWD
. Когда оболочка собирается отобразить приглашение, она снова выполняет расширение переменной, и на этот раз, поскольку $PS1
содержит $PWD
,без\
, оболочка успешно расширяет его до текущего каталога.
Тот же подход можно использовать для создания динамических имен переменных в скриптах оболочки ( rcNG
система NetBSD использует это довольно широко, особенно в скриптах, управляющих сетевыми интерфейсами, где количество обозначений сетевых адаптеров в NetBSD и FreeBSD делает нецелесообразным явное кодирование для каждого из них).