Bash: 프롬프트에 종료 상태 표시:

Bash: 프롬프트에 종료 상태 표시:
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)'

다음은 올바른 exitStatus를 제공하지만 색상 변수는 확장되지 않습니다.

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

그러나 다음은 색상을 제공하지만 종료 상태는 업데이트되지 않습니다.

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

이를 수행하는 올바른 방법은 무엇입니까? ExitStatus와 색상이 모두 작동하도록 이 문제를 어떻게 해결할 수 있습니까?

답변1

Giles는 귀하의 주요 문제를 지적했지만 저는 이를 다른 방식으로 설명하려고 합니다.

배쉬는 설명했다특수 프롬프트 이스케이프오직앞으로프롬프트에서 변수를 확장합니다. 즉, \e프롬프트에서 확장된 변수를 사용하면 에서 직접 작동하더라도 아무런 효과가 없습니다 PS1.

예를 들어, 예상대로 작동하며 빨간색 텍스트가 표시됩니다.

PS1='\e[1;31m this is in red '

하지만 그렇지 않습니다. 단지 \e프롬프트에 텍스트를 추가할 뿐입니다.

RED='\e[1;31m'
PS1="$RED not in red "

색상 이스케이프를 변수에 저장하려면 ANSI-C 따옴표( $'...')를 사용하여 변수에 리터럴 이스케이프 문자를 배치할 수 있습니다.

이를 위해 GREEN, 및 RED의 정의를 변경하여 NONE해당 값이 실제 이스케이프 시퀀스가 ​​되도록 할 수 있습니다.

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

이렇게 하면 첫 번째 PS1작은따옴표가 작동합니다.

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

그러나 이렇게 하면 두 번째 문제에 직면하게 됩니다.

실행하고 계속해서 Up Arrow누르면 Home커서가 줄의 시작 부분으로 돌아가지 않습니다.

이 문제를 해결하려면 색상 이스케이프 시퀀스를 PS1포함 \[하고 둘러싸도록 변경하세요.\]

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

get_exit_status출력에 인쇄(종료 코드) 및 인쇄되지 않는 문자(색상 코드)가 포함되어 있고 프롬프트에서 제대로 표시할 수 없기 때문에 여기서는 올바르게 사용할 수 없습니다 . 배치하면 \[...\]불완전한 인쇄로 표시되며 이는 잘못된 것입니다. 올바른 색상 코드를 인쇄한 다음 \[...\]프롬프트에 래핑 하도록 함수를 변경해야 합니다 .

답변2

을 실행하면 PS1='${RED}\h $(get_path) ${exitStatus}${NONE} '변수 PS1가 프롬프트 이스케이프 시퀀스인 으로 ${RED}\h $(get_path) ${exitStatus}${NONE}설정 됩니다.\h뒤쪽에프롬프트 순서가 확장(생성 ${RED}darkstar $(get_path) ${exitStatus}${NONE})되고 쉘은 변수 확장과 같은 일반적인 확장을 수행합니다. 다음과 유사한 디스플레이 프롬프트가 표시됩니다 \e[1;31mdarkstar PATH 0\e[m. 그 과정에서 \e시퀀스를 실제 이스케이프 문자로 확장하는 것은 없습니다.

을 실행하면 PS1="${RED}\h $(get_path) ${exitStatus}${NONE} "PS1변수가 로 설정됩니다 \e[1;31m\h PATH 0\e[m. 변수 RED, exitStatusNONE할당 시 확장됩니다. 그러면 프롬프트에는 세 개의 프롬프트 이스케이프 시퀀스( \e, \h\e다시)가 포함됩니다. 이 단계에서는 확장 가능한 셸 변수가 없습니다.

색상을 보려면 실제 이스케이프된 문자를 포함하는 색상 변수가 필요합니다. 다음을 수행할 수 있습니다.

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

$'…'백슬래시 8진수 시퀀스와 일부 백슬래시 문자 시퀀스를 확장합니다(예: \n) \e. 귀하의 팁에 세 가지 추가 변경 사항을 적용했습니다.

  • \[…\]색상 변경 명령과 같은 인쇄되지 않는 시퀀스를 사용합니다 . 그렇지 않으면 bash가 프롬프트의 너비를 계산할 수 없기 때문에 디스플레이가 깨질 것입니다.
  • \w현재 디렉토리를 인쇄하는 데 사용되는 내장 이스케이프 시퀀스입니다.
  • 처음부터 복잡한 내용이 없다면 $?프롬프트에 복잡한 내용을 표시할 필요가 없습니다 .PROMPT_COMMAND

답변3

노력하다:

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

답변4

여기요- 이것은 Ubuntu 및 기타 Linux(Linuxen?)의 나(TM)에게 적합합니다.

종료 코드 감지 기능을 추가하는 이유는 $PS1하나의 호스트가 .bashrc를 읽기 전에 읽기 전용으로 설정되어 있기 때문입니다 $PROMPT_COMMAND.

관련 정보