Установка переменной в bash PS1

#bash #ps1

#bash #ps1

Вопрос:

Я пытаюсь настроить свое приглашение bash, и у меня возникли проблемы с несколькими условиями.

Мой текущий PS1 выглядит следующим образом.

 export PS1="
$PS1USERCOLORu
$COLOR_WHITE@
$COLOR_GREENh
$COLOR_WHITE:
$COLOR_YELLOWW
`if type parse_git_branch > /dev/null 2>amp;1; then parse_git_branch; fi`
`if [ $? = 0 ]; then echo -e '$COLOR_WHITE'; else echo -e '$COLOR_RED'; fi`$     
$COLOR_WHITE"
  
  • В первых 6 строках просто задаются обычные PS1 параметры.

  • Затем строка 7 вызывает функцию для отображения текущей ветви git и статуса, если это применимо.

  • Затем строка 8 проверяет код возврата предыдущей команды и изменяет цвет $ в конце.

  • Строка 9 возвращает приглашению белый цвет, готовый для команды пользователя.

Однако строка 8 отвечает на код возврата из функции строки 7, а не на предыдущую команду, как я сначала ожидал.

Я попытался переместить строку 8 перед строкой 7, и все работает так, как должно. Но я не хочу, чтобы строка 8 предшествовала строке 7, $ должна быть в конце.

Ранее я пытался установить переменную в качестве значения $? , а затем протестировать эту переменную следующим образом

 export PS1="
`RETURN=$?`
$PS1USERCOLORu
$COLOR_WHITE@
$COLOR_GREENh
$COLOR_WHITE:
$COLOR_YELLOWW
`if type parse_git_branch > /dev/null 2>amp;1; then parse_git_branch; fi`
`if [ $RETURN = 0 ]; then echo -e '$COLOR_WHITE'; else echo -e '$COLOR_RED'; fi`$     
$COLOR_WHITE"
  

Но это не работает.

У кого-нибудь есть идеи, как решить мою проблему?

Комментарии:

1. Я бы разделил все операторы if на отдельную функцию или скрипт и протестировал независимо. возвращает цвет в виде строки

2. Вы устанавливаете переменную во вложенной оболочке. Это не переносится в другую вложенную оболочку или родительскую оболочку.

3. Это имеет смысл! Есть идеи, как это сделать правильно?

4. Не используйте две вложенные оболочки для двух тестов. Используйте одну из них, установите RETURN в начале этой вложенной оболочки, а затем используйте ее в конце.

5. Смотрите также Как получить зеленые / красные терминалы под OpenBSD? и Функция bash с отслеживанием состояния

Ответ №1:

Правильный способ — использовать PROMPT_COMMAND вот так:

 prompt_cmd () {
    LAST_STATUS=$?
    PS1="$PS1USERCOLORu"
    PS1 ="$COLOR_WHITE@"
    PS1 ="$COLOR_GREENh"
    PS1 ="$COLOR_WHITE:"
    PS1 ="$COLOR_YELLOWW"
    if type parse_git_branch > /dev/null 2>amp;1; then
        PS1 =$(parse_git_branch)
    fi
    if [[ $LAST_STATUS = 0 ]]; then
        PS1 ="$COLOR_WHITE"
    else
        PS1 ="$COLOR_RED"
    fi
    PS1 ='$'
    PS1 ="$COLOR_WHITE"
}
  

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

Пара замечаний:

  1. Вы должны сохранить $? в первой строке кода, прежде чем значение, которое вы хотите, будет перезаписано.
  2. Я использую двойные кавычки для большинства шагов, за исключением $ ; вы могли бы использовать PS1 ="\$" , если хотите.

Комментарии:

1. Это превосходно и гораздо элегантнее. Я использовал ее именно так, хотя и добавил пробел после $ .

Ответ №2:

Стандартным решением этой проблемы является использование bash переменной окружения PROMPT_COMMAND . Если вы присвоите этой переменной имя функции оболочки, указанная функция будет выполняться перед отображением каждого bash запроса. Затем внутри указанной функции вы можете настроить любые переменные, которые вы хотите. Вот как я делаю почти именно то, что вы ищете в моем .bashrc :

 titlebar_str='[e]0;u@h: wa]'
time_str='[e[0;36m]t'
host_str='[e[1;32m]h'
cwd_str='[e[0;33m]$MYDIR'
git_str='[e[1;37m]`/usr/bin/git branch --no-color 2> /dev/null | /bin/grep -m 1 ^* | /bin/sed -e "s/* (.*)/ [1]/"`[e[0m]'
dolr_str='[e[0;`[ $lastStatus -eq 0 ] amp;amp; echo 32 || echo 31`m]$ [e[0m]'
export PS1="$titlebar_str$time_str $host_str $cwd_str$git_str$dolr_str"

function prompt_func {
    # Capture the exit status currently in existence so we don't overwrite it with
    # any operations performed here.
    lastStatus=$?

    # ... run some other commands (which will have their own return codes) to set MYDIR
}

export PROMPT_COMMAND=prompt_func
  

Теперь bash будет запускаться prompt_func перед отображением каждого нового приглашения. Статус завершения предыдущей команды фиксируется в lastStatus . Поскольку git_str , dolr_str и т.д. Определяются в одинарных кавычках, переменные (включая lastStatus ) и команды внутри них затем повторно вычисляются при разыменовании bash PS1 .

Комментарии:

1. Используя PROMPT_COMMAND , вы обычно просто условно устанавливаете значение, например, dolr_str внутри функции, вместо того, чтобы пытаться встроить команду в значение dolr_str .

2. Верно. Вышесказанное является результатом множества правок, сделанных в самых разных состояниях ума. 🙂

Ответ №3:

Проблема решена!

Мне нужно использовать PROMPT_COMMAND переменную для установки RETURN переменной. PROMPT_COMMAND это команда, которая вызывается перед PS1 загрузкой.

Мой скрипт теперь выглядит следующим образом

 PROMPT_COMMAND='RETURN=$?'

export PS1="
$PS1USERCOLORu
$COLOR_WHITE@
$COLOR_GREENh
$COLOR_WHITE:
$COLOR_YELLOWW
`if type parse_git_branch > /dev/null 2>amp;1; then parse_git_branch; fi`
`if [[ $RETURN = 0 ]]; then echo -e '$COLOR_WHITE'; else echo -e '$COLOR_RED'; fi`$     
$COLOR_WHITE"
  

Комментарии:

1. С таким же успехом вы могли бы выполнить полный тест if в PROMPT_COMMAND и задать переменную со строкой для использования в PS1 .