Bash: muestra el estado de salida en el prompt:

GREEN="\e[1;32m" RED="\e[1;31m" NONE="\e[m" get_exit_status(){ es=$? if [ $es -eq 0 ] then echo -e "${GREEN}${es}${NONE}" else echo -e "${RED}${es}${NONE}" fi } get_path(){ #dummy function echo "PATH" } PROMPT_COMMAND='exitStatus=$(get_exit_status)' 

Lo siguiente me da el exitStatus correcto, pero las variables de color no se expanden:

 PS1='${RED}\h $(get_path) ${exitStatus}${NONE} ' 

Sin embargo, el siguiente, me da los colors, pero el estado de salida no se actualiza:

 PS1="${RED}\h $(get_path) ${exitStatus}${NONE} " 

¿Cuál es la forma correcta de hacer esto? ¿Cómo puedo solucionar esto para que tanto exitStatus como los colors funcionen?

Gilles identificó tu problema principal, pero quería intentar explicarlo de otra manera.

Bash efectivamente llama echo en tu PS1 , no echo -e .

Entonces, es como si estuvieras haciendo:

 echo '\e[1;32m\h\e[m' 

Si intenta ejecutar eso, verá que no funciona.

Pero bash te da una forma de escribir caracteres especiales que no requieren el uso de echo -e . Parece $'\octal number' .

El personaje especial en todas las secuencias de escape es \e , que solo significa Escape. El valor octal de Escape es \033 .

Entonces, queremos que se amplíe a esto:

 echo $'\033[1;31m'"${HOSTNAME}"$'\033[m' 

Para hacer esto, puede cambiar su definición de GREEN , RED y NONE , de modo que su valor sea la secuencia de escape real.

 GREEN=$'\033[1;32m' RED=$'\033[1;31m' NONE=$'\033[m' 

Si lo haces, tu primera PS1 con las comillas simples debería funcionar:

 PS1='${RED}\h $(get_path) ${exitStatus}${NONE} ' 

Sin embargo, entonces tendrás un segundo problema.

Intenta ejecutar eso, luego presiona Flecha arriba , luego Inicio , y tu cursor no volverá al comienzo de la línea.

Para solucionarlo, cambie PS1 para include \[ y \] alnetworkingedor de las secuencias de escape de color, por ejemplo

 PS1='\[${RED}\]\h $(get_path) \[${exitStatus}\]\[${NONE}\] ' 

Y todo debería estar funcionando.

(No estoy seguro de por qué poner \[ around ${exitStatus} funciona, porque el número de estado de salida no debería tener los que están a su alnetworkingedor, pero parece que me funciona).

Cuando ejecuta PS1='${RED}\h $(get_path) ${exitStatus}${NONE} ' , la variable PS1 se establece en ${RED}\h $(get_path) ${exitStatus}${NONE} , donde solo \h es una secuencia de escape rápido. Después de que las secuencias de request se expanden (rindiendo ${RED}darkstar $(get_path) ${exitStatus}${NONE} ), el shell realiza las expansiones habituales tales como expansiones de variables. \e[1;31mdarkstar PATH 0\e[m un post que se ve como \e[1;31mdarkstar PATH 0\e[m . Nada en el path expande las secuencias a los personajes de escape reales.

Cuando ejecuta PS1="${RED}\h $(get_path) ${exitStatus}${NONE} " , la variable PS1 se establece en \e[1;31m\h PATH 0\e[m . Las variables RED , exitStatus y NONE se expanden en el momento de la asignación. A continuación, el aviso contiene tres secuencias de escape rápido ( \e , \h , y \e nuevamente). No hay variables de shell para expandir en esta etapa.

Para ver colors, necesita que las variables de color contengan caracteres de escape reales. Puedes hacerlo de esta manera:

 RED=$'\033[1;31m' NONE=$'\033[m' PS1='\[${RED}\]\h \w $?\[${NONE}\] ' 

$'…' amplía las secuencias de barra invertida y octal y algunas secuencias de barra invertida como \n , pero sin include \e . Hice otros tres cambios a su post:

  • Utilice \[…\] torno a secuencias que no sean de printing, como commands de cambio de color. De lo contrario, su pantalla terminará distorsionada porque bash no puede determinar el ancho del aviso.
  • \w es una secuencia de escape incorporada para imprimir el directory actual.
  • No necesitas nada complicado para mostrar $? en el aviso si no tiene un PROMPT_COMMAND en primer lugar.

Aquí tienes : This Works For Me (TM) en Ubuntu y otros Linuxes (Linuxen?).

La razón para poner la detección de código de salida en $PS1 es que un host tiene un set $PROMPT_COMMAND solo $PROMPT_COMMAND antes de leer .bashrc.

Tratar:

 PS1='`exitStatus=$?;if [ $exitStatus -eq 0 ];then echo "\['${GREEN}'\]";else echo "\['${RED}'\]";fi;echo "\h $(get_path) ${exitStatus}${NONE}"`' 

Este es el enfoque que he seguido, evita el uso de PROMPT_COMMAND .

 # This function is called from a subshell in $PS1, # to provide a colourised visual indicator of the exit status of the last run command __COLOURISE_EXIT_STATUS() { # uncomment the next line for exit code output after each command, useful for debugging and testing #printf -- "\nexit code: $1\n" >&2 [[ 0 == "$1" || 130 == "$1" ]] && printf -- "$GREEN" || printf -- "$RED" } 

Entonces mi $PS1 es el siguiente:

 PS1='# ${debian_chroot:+($debian_chroot)}'"${GREEN}\u${YELLOW}@${DARK_YELLOW}\h${WHITE}:${LIGHT_BLUE}\w${WHITE}\n"'\[$(__COLOURISE_EXIT_STATUS $?)\]# \$'"\[${WHITE}\] " 

Para PROMPT_COMMAND , es más limpio definir una function y usar eso:

 prompt_command() { # ... } PROMPT_COMMAND=prompt_command