В чем разница между PS1 и PROMPT COMMAND


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

PS1="Blah Blah Blah"

и

PROMPT_COMMAND="Blah Blah Blah"

(и некоторые используют оба) при установке подсказки в оболочке bash. В чем разница между ними? Поиск SO и даже немного более широкий поиск google не дают мне результатов, поэтому даже ссылка на нужное место для поиска ответа будет оценена по достоинству.

5 80

5 ответов:

со страницы GNU Bash doc:http://www.gnu.org/software/bash/manual/bashref.html

PROMPT_COMMAND
    If set, the value is interpreted as a command to execute before
    the printing of each primary prompt ($PS1).

Я никогда не использовал его, но я мог бы использовать это, когда у меня была только СГ.

PROMPT_COMMAND может содержать обычные операторы bash, тогда как переменная PS1 может также содержать специальные символы, такие как '\h' для имени хоста, в переменной.

например, вот моя подсказка bash, которая использует как PROMPT_COMMAND, так и PS1. Код bash в PROMPT_COMMAND определяет, в какой ветви git вы можете находиться, и отображает это в приглашении вместе со статусом выхода последнего запущенного процесса, именем хоста и базовым именем pwd. Переменная RET сохраняет возвращаемое значение последней выполненной программы. Это удобно, чтобы увидеть, если была ошибка и код ошибки последней программы, которую я запустил в терминале. Обратите внимание на внешний', окружающий все выражение PROMPT_COMMAND. Он включает в себя PS1, так что эта переменная повторно оценивается каждый раз, когда оценивается переменная PROMPT_COMMAND.

PROMPT_COMMAND='RET=$?;\
  BRANCH="";\
  ERRMSG="";\
  if [[ $RET != 0 ]]; then\
    ERRMSG=" $RET";\
  fi;\
  if git branch &>/dev/null; then\
    BRANCH=$(git branch 2>/dev/null | grep \* |  cut -d " " -f 2);\
  fi;
PS1="$GREEN\u@\h $BLUE\W $CYAN$BRANCH$RED$ERRMSG $ $LIGHT_GRAY";'

пример вывода выглядит так в каталоге без git:

sashan@dhcp-au-122 Documents  $ false
sashan@dhcp-au-122 Documents  1 $ 

и в каталоге git'вы видите ветку имя:

sashan@dhcp-au-122 rework mybranch $ 

обновление

после прочтения комментариев и ответа Боба я думаю, что писать его так, как он описывает, лучше. Это более ремонтопригодно, чем то, что я первоначально написал выше, где переменная PS1 установлена внутри PROMPT_COMMAND, которая сама по себе является супер сложной строкой, которая оценивается во время выполнения bash. Это работает, но это сложнее, чем должно быть. Справедливости ради я написал, что PROMPT_COMMAND для себя около 10 лет назад, и это сработало и я не слишком много об этом думал.

для тех, кому интересно, как я изменил свои вещи, я в основном поместил код для PROMPT_COMMAND в отдельный файл (как описал Боб), а затем повторил строку, которую я намерен быть PS1:

GREEN="\[3[0;32m\]"
CYAN="\[3[0;36m\]"
RED="\[3[0;31m\]"
PURPLE="\[3[0;35m\]"
BROWN="\[3[0;33m\]"
LIGHT_GRAY="\[3[0;37m\]"
LIGHT_BLUE="\[3[1;34m\]"
LIGHT_GREEN="\[3[1;32m\]"
LIGHT_CYAN="\[3[1;36m\]"
LIGHT_RED="\[3[1;31m\]"
LIGHT_PURPLE="\[3[1;35m\]"
YELLOW="\[3[1;33m\]"
WHITE="\[3[1;37m\]"
RESTORE="\[3[0m\]" #0m restores to the terminal's default colour

if [ -z $SCHROOT_CHROOT_NAME ]; then
    SCHROOT_CHROOT_NAME=" "
fi
BRANCH=""
ERRMSG=""
RET=
if [[ $RET != 0 ]]; then
    ERRMSG=" $RET"
fi
if which git &>/dev/null; then
    BRANCH=$(git branch 2>/dev/null | grep \* |  cut -d " " -f 2)
else
    BRANCH="(git not installed)"
fi
echo "${GREEN}\u@\h${SCHROOT_CHROOT_NAME}${BLUE}\w \
${CYAN}${BRANCH}${RED}${ERRMSG} $ $RESTORE"

и в моем .bashrc

function prompt_command {
    RET=$?
    export PS1=$(~/.bash_prompt_command $RET)
}
PROMPT_DIRTRIM=3
export PROMPT_COMMAND=prompt_command

разница в том, что PS1-это фактическая строка приглашения, а PROMPT_COMMAND-это команда, которая выполняется непосредственно перед приглашением. Если вы хотите самый простой и гибкий способ построения приглашения, попробуйте следующее:

положите это в свой .bashrc следующее:

function prompt_command {
  export PS1=$(~/bin/bash_prompt)
}
export PROMPT_COMMAND=prompt_command

затем напишите скрипт (bash, perl, ruby: ваш выбор) и поместите его в ~/bin/bash_prompt.

скрипт может использовать любую информацию, которую он любит строить запрос. Это гораздо проще ИМО, потому что вы не нужно изучать несколько барочный язык подстановки, который был разработан только для переменной PS1.

вы можете подумать, что вы могли бы сделать то же самое, просто установив PROMPT_COMMAND непосредственно в ~/bin/bash_prompt и установив PS1 в пустую строку. Сначала это кажется работающим, но вскоре вы обнаружите, что код readline ожидает, что PS1 будет установлен в фактическое приглашение, и когда вы прокручиваете backwords в истории, в результате все запутывается. Этот способ вызывает PS1 для всегда отражайте последнее приглашение (поскольку функция устанавливает фактический PS1, используемый вызывающим экземпляром оболочки), и это делает readline и историю команд хорошо работать.

С man bash:

PROMPT_COMMAND

если задано, значение выполняется как команда перед выдачей каждого основного запроса.

PS1

значение этого параметра расширяется (см. запрос ниже) и используется в качестве основной строки запроса. Значение по умолчанию-"\s - \v\$ ".

если вы просто хотите установить строку запроса с помощью это хватит:

PS1='user \u on host \h$ '

если вы хотите сделать что-то еще непосредственно перед печатью приглашения, используйте PROMPT_COMMAND. Например, если вы хотите синхронизировать кэширования записи на диск, вы можете написать:

PROMPT_COMMAND='sync'

разница в том, что

  • если вы выводите неполную строку из PROMPT_COMMAND, Он будет винт ваш Баш подскажет
  • PS1 заменяет \H и друзьями
  • PROMPT_COMMAND работает его содержимое, PS1 использует его содержимое в качестве подсказки.

PS1 делает переменное расширение и подстановку команд в каждом приглашении, не нужно использовать PROMPT_COMMAND присвоить значение PS1 или для выполнения произвольного кода. вы можете легко сделать export PS1='$(uuidgen) $RANDOM' раз в .bash_profile, просто используйте одинарные кавычки