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

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

PS1="Blah Blah Blah"

и некоторые используют

PROMPT_COMMAND="Blah Blah Blah"

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

+96
17 июн. '10 в 1:27
источник поделиться
6 ответов

На странице 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).

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

+50
17 июн. '10 в 1:38
источник

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="\[\033[0;32m\]"
CYAN="\[\033[0;36m\]"
RED="\[\033[0;31m\]"
PURPLE="\[\033[0;35m\]"
BROWN="\[\033[0;33m\]"
LIGHT_GRAY="\[\033[0;37m\]"
LIGHT_BLUE="\[\033[1;34m\]"
LIGHT_GREEN="\[\033[1;32m\]"
LIGHT_CYAN="\[\033[1;36m\]"
LIGHT_RED="\[\033[1;31m\]"
LIGHT_PURPLE="\[\033[1;35m\]"
YELLOW="\[\033[1;33m\]"
WHITE="\[\033[1;37m\]"
RESTORE="\[\033[0m\]" #0m restores to the terminal default colour

if [ -z $SCHROOT_CHROOT_NAME ]; then
    SCHROOT_CHROOT_NAME=" "
fi
BRANCH=""
ERRMSG=""
RET=$1
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
+61
17 июн. '10 в 1:45
источник

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

Поместите это в свой .bashrc:

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

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

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

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

+42
19 июн. '12 в 18:57
источник

Из man bash:

PROMPT_COMMAND

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

PS1

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

Если вы просто хотите установить строку приглашения, достаточно использовать только PS1:

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

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

PROMPT_COMMAND='sync'
+8
20 июл. '14 в 4:07
источник

Да, так, чтобы попытаться действительно прибить это:

  • PROMPT_COMMAND - это удобная переменная/функция удобства bash, но, строго говоря, нет ничего, что нельзя сделать, используя только PS1, верно?

Я имею в виду, если кто-то хочет установить другую переменную с областью видимости вне приглашения: в зависимости от оболочки, эту переменную, вероятно, нужно будет сначала объявить за пределами $PS1 или (в худшем случае), возможно, придется привыкнуть к чему-то, ожидающему FIFO до вызова $PS1 (и снова в состоянии $PS1 в конце $PS1); \u \h может вызвать некоторые проблемы, особенно если вы используете какое-то необычное регулярное выражение; но в противном случае: можно выполнить все, что может PROMPT_COMMAND, используя подстановку команд в $PS1 (и, возможно, в угловых случаях, явные подоболочки)?

Правильно?

0
07 мая '19 в 7:57
источник

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

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

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

0
10 сент. '18 в 17:08
источник

Посмотрите другие вопросы по меткам или Задайте вопрос