PS1 = '$ (pwd)', почему это работает и почему это отличается от PS1 = $ (pwd)

18

Почему, когда я ввожу эту команду, приглашение изменится на мой каталог?

PS1='$(pwd)'

Я использую одинарные кавычки, что означает отсутствие интерполяции, иначе echo '$(pwd)'—— →$(pwd)

Кроме того, скажем, что мы выяснили, почему это работает ... почему оно функционирует иначе PS1=$(pwd)? (без кавычек вообще)

Под другим я подразумеваю, что если я использую кавычки, то приглашение будет продолжать меняться в моем текущем каталоге, когда я перемещаюсь через терминал. Но если я не использую кавычки, то приглашение всегда будет оставаться в том каталоге, в котором я находился при первом вводе командыPS1=$(pwd)

Почему?

HashWizard
источник
2
Сохраните несколько циклов ЦП и используйте эквивалентный PS1 = '$ PWD'
jlliagre

Ответы:

29

Когда вы просто присваиваете значение переменной, $(...)выражение вычисляется, если оно не заключено в одинарные кавычки (или не имеет обратной косой черты). Чтобы понять, попробуйте сравнить эти два:

A=$(pwd)
echo "$A"
B='$(pwd)'
echo "$B"

Значение Aсразу становится строкой /home/yourusernameи, очевидно, не запоминается, откуда взялась эта строка, оно остается прежним, даже если вы меняете каталог. Однако значение Bстановится литеральной строкой $(pwd)без интерпретации.

Теперь в значении PS1чего-то особенного происходит: всякий раз, когда выводится подсказка, интерпретируются определенные специальные конструкции, например, подстановка команды $(...)выполняется точно так же, как это было сделано выше при назначении Aпеременной. Очевидно, что если вы PS1содержите буквальную строку вашего домашнего каталога (как указано выше A), то это никак не изменится. Но если она содержит строку $(pwd)(как указано выше B), то она оценивается каждый раз, когда выводится приглашение, и, следовательно, отображается ваш фактический каталог.

Эгмонт
источник
14

Как в bash, так и в zsh, значение PS1не используется как приглашение как есть, оно подвергается некоторым расширениям. Эти правила отличаются для двух оболочек, но в обеих случаях одна из шага заключается в выполнении «доллар» разложение (переменная подстановки, подстановки команд, арифметическая оценка) с таким же синтаксисом , как и в обычном синтаксисе оболочки ( , , или , , ) ,$VARIABLE${VARIABLE}$(COMMAND)`COMMAND`$((EXPRESSION))$[EXPRESSION]

  • В bash расширение доллара включено по умолчанию, но его можно отключить с помощью shopt -u promptvars.
  • В zsh расширение доллара по умолчанию отключено, но многие люди (и большинство конфигурационных фреймворков, которые вы найдете в Интернете) включают его setopt prompt_subst.

Если в приглашении включено расширение доллара, PS1='$(pwd)'задается PS16-значное значение $(pwd)и, следовательно, происходит $(pwd)подстановка и, следовательно, pwdкоманда, которая будет выполняться каждый раз, когда оболочка отображает новое приглашение. С другой стороны, PS1=$(pwd)устанавливает PS1на то, что является текущим рабочим каталогом оболочки в данный момент. Если у вас отключено расширение доллара, то PS1='$(pwd)'приглашение будет буквальной строкой $(pwd).

Обратите внимание, что есть более удобные способы получить рабочий каталог в приглашении:

  • В bash, с обратной косой чертой, такой как \w, которая сокращает ваш домашний каталог до ~и может быть обрезана установкой PROMPT_DIRTRIM.
  • В Zsh, с процентами избежать таких как %/или%~ ( %/так же , как $PWD, %~сокращает домашние каталоги), которые могут иметь подрезки настройки.
  • В любой оболочке (и любой другой оболочке в стиле Борна) $PWDэто эквивалентно $(pwd): вам не нужно запускать подпроцесс для получения текущего рабочего каталога.
Жиль "ТАК - перестань быть злым"
источник
7

Потому что без кавычек, $ (pwd) оценивается, когда установлен PS1. С кавычками оценка $ (pwd) откладывается до отображения приглашения.

Без кавычек PS1 устанавливается в текущий каталог в то время, когда PS1 установлен. С одинарными кавычками PS1 установлен в $ (pwd), что означает, что он будет оценивать и печатать текущий каталог каждый раз, когда отображается подсказка.

farhangfarhangfar
источник