인쇄되지 않는 이스케이프 시퀀스: 언제?

인쇄되지 않는 이스케이프 시퀀스: 언제?

나는 최근에 터미널에서 색상을 많이 다루었기 때문에 이스케이프 시퀀스를 사용했습니다. 나는 Bash 맨페이지의 관련 섹션과 웹에서 많은 유용한 페이지를 읽었습니다.

예를 들어 멋지고 다채로운 Bash 프롬프트 등 내가 원하는 대부분을 얻었습니다. 즉, "비인쇄 이스케이프 시퀀스" 문자를 사용해야 하는 경우(또는 사용해야 하는 경우)에 대해 여전히 약간 혼란스럽습니다. 그것들은 \[과 입니다 \].

만약 내가아니요프롬프트를 정의할 때 PS1에서 이를 사용하면 프롬프트가 올바르게 표시되지 않습니다. 사용하면 모든 것이 괜찮습니다. 좋아요

그러나 PS1 외부에서는 동일하게 작동하지 않는 것 같습니다. 예를 들어 스크립트를 더 읽기 쉽게 만들기 위해 $RGB_PURPLE간단한 함수를 통해 설정되는 변수를 정의했습니다 c8_rgb(). 최종 결과는 변수 \[\e[01;38;05;129m\]에 굵은 보라색 전경색을 켜는 값이 포함된다는 것입니다.

PS1에서 이 변수를 사용하면 예상한 대로 작동합니다. 통과하거나 printf사용 하면 echo -e"반"이 작동합니다. 이 명령 printf "${RGB_PURPLE}TEST${COLOR_CLR}\n"( COLOR_CLR텍스트 속성을 재설정하는 이스케이프 시퀀스는 어디에 있습니까?)은 다음과 같이 표시됩니다. \[\]TEST\[\]여기서 첫 번째 \[와 마지막을 제외한 모든 항목은 \]보라색으로 표시됩니다.

왜 차이가 있나요? 이러한 괄호가 인쇄되어 있지만 터미널에서 처리되지 않는 이유는 무엇입니까? 다른 방법으로 인쇄할 때와 마찬가지로 프롬프트의 일부로 인쇄할 때에도 동일하게 처리되었으면 좋았을 것입니다. 나는 이 변화를 이해하지 못한다.

경험적으로 보면 이러한 역할은~ 해야 하다프롬프트 정의에 사용되는 반면해서는 안 된다거의 모든 다른 상황에서 사용할 수 있습니다. 이로 인해 c8_rgb()이스케이프 시퀀스 생성 및 출력을 처리하기 위해 위에서 언급한 것과 같은 범용 함수를 사용하기가 어렵습니다. 함수는 해당 결과가 프롬프트 구성에 있는지 아니면 다른 곳에 있는지 알 수 있는 방법이 없기 때문입니다.

한 가지 더 빠른 관련 질문: 이스케이프 시퀀스 출력 측면에서 본질적으로 동일합니까 echo -e? printf나는 보통 printf를 사용하는데, 다른 것보다 더 선호할 이유가 있나요?

이 명백한 뉘앙스를 설명할 수 있는 사람이 있나요? 터미널에서 이스케이프 시퀀스(보통 색상만 해당)를 사용할 때 알아야 할 다른 이상한 사항이 있습니까? 감사해요!

답변1

$PS1에서 인쇄되지 않는 문자를 사용할 때 "인쇄되지 않는 이스케이프 시퀀스"가 필요합니다. 명령줄을 편집할 때 화면을 올바르게 업데이트하려면 bash가 커서의 위치를 ​​알아야 하기 때문입니다. Bash는 $PS1 프롬프트의 문자 수(커서가 있는 열 번호)를 계산하여 이를 수행합니다.

하지만 인쇄되지 않는 시퀀스를 $PS1에 넣으면 카운트가 잘못되고, 명령줄을 편집하면 줄이 엉망이 될 수 있습니다. 따라서 포함된 바이트를 계산하지 않아야 함을 나타내기 위해 \[및 플래그가 도입되었습니다 .\]

답변2

나는 다음을 사용하여 충분한 해결책을 찾았습니다.8진수전체 이스케이프 시퀀스이며 구분 기호의 readline 형식을 사용합니다. PS1, echo -e 및 printf는 모두 정확히 동일한 문자열을 사용하여 이러한 방식으로 올바른 작업을 수행합니다. 저는 이것을 OSX의 Bash 4와 Linux의 Bash 3에서 테스트했습니다.

여기 답변에서 \001 및 \002에 대한 아이디어를 얻었습니다.https://superuser.com/questions/301353/escape-non-printing-characters-in-a-function-for-a-bash-prompt?rq=1

예:

$ TextGreen='\001\033[0;32m\002'
$ TextReset='\001\033[0m\002'
$ SomeString="${TextGreen}prompt_stuph${TextReset} \$ "
$ #
$ # now all of the following work as expected
$ #
$ PS1="$SomeString"
$ printf "$SomeString"
$ echo -e "$SomeString"

답변3

마찬가지로 ␛[01;38;05;129m첫 번째 문자 는 터미널 이스케이프 시퀀스인 ASCII 이스케이프 문자(U+0027)입니다. 이는 터미널에 색상 129로 굵고 깜박이는 텍스트를 표시하기 시작하도록 지시합니다. 이스케이프 문자(inside , in , in 및 in ) \e에 대한 bash 구문입니다 .$'…'PS1echo -eprintf

\[터미널 이스케이프 시퀀스가 ​​아니며 \]bash 프롬프트 이스케이프 시퀀스입니다. 터미널로 전송되지 않고 bash에 의해 해석됩니다. 그들의 목적은 그 사이에 있는 문자가 인쇄되지 않는 문자임을 bash에게 알려주는 것입니다. 따라서 프롬프트의 너비는 실제로 안에 없는 문자의 수입니다 \[…\]. Bash는 줄 편집기에서 커서 위치를 계산하기 위해 프롬프트의 너비를 알아야 합니다.

\[…\]함수가 프롬프트 문자열 외부에서 사용되도록 의도된 경우 해당 함수를 출력해서는 안 됩니다. 프롬프트 문자열에 및 를 직접 포함합니다 \[.\]

관련 정보