터미널의 백스페이스 키 동작

터미널의 백스페이스 키 동작

백스페이스( ) 문자의 동작에 관한 내용입니다 \b. 다음과 같은 C 프로그램이 있습니다.

int main() {
    printf("Hello\b\b");
    sleep(5);
    printf("h\n");
    return 0;
}

내 터미널의 출력은 다음과 같습니다.

Helho

커서가 다음 줄의 첫 번째 위치로 이동합니다.

첫째, 전체 내용은 5초의 휴면 후에만 인쇄되므로 커널에서 터미널로의 출력이 라인 버퍼링된 것으로 추론됩니다. 이제 내 질문은 다음과 같습니다.

  1. 두 칸 뒤로 이동하여 (두 번째) 위치에 도달 하였으므로 \b\b교체와 유사한 방법으로 교체해야 합니다 l. 왜 안 돼?lho\n
  2. 줄을 삭제하면 삭제하지 않고 두 문자를 printf("h\n");인쇄 하고 반환합니다. Hello나는 이것이 비파괴적인 백스페이스 키 때문이라는 것을 다른 답변에서 얻었습니다. 입력과 출력이 다르게 동작하는 이유는 무엇입니까? 즉, 터미널에 무언가를 입력하고(동일한 프로그램에서도) 백스페이스를 누르면 마지막 문자는 삭제되지만 출력은 삭제되지 않습니다. 왜?

도움이 된다면 Ubuntu 시스템의 xterm 터미널에서 bash를 사용하고 있습니다.

답변1

첫째, 전체 내용은 5초의 휴면 후에만 인쇄되므로 커널에서 터미널로의 출력이 라인 버퍼링된 것으로 추론됩니다.

아니요, 귀하의 결과물프로그램커널에 대한 라인 버퍼링이 있습니다. 이는 터미널인 stdio경우 기본 동작 입니다 . 출력 버퍼링을 끄는 stdout호출이 추가되었습니다 . 바라보다setbuf(stdout, NULL)stdoutsetbuf(3).

  1. 그때의 위치로 두 칸 뒤로 이동한 것이므로 \b\b교체하는 방법과 유사하므로 l교체해야 합니다. 왜 안 돼?lho\n

개행 문자는 단순히 커서를 이동하고 화면을 스크롤하기 때문에 터미널의 문자 모양 위치를 차지하기 위해 보이는 문자로 인쇄되지 않습니다. 이것이 문자 모양을 대체한다고 가정하면 어떤 모습일까요?

  1. 동일한 프로그램에서 무언가를 입력한 다음 백스페이스를 누르면 마지막 문자는 삭제되지만 출력은 삭제되지 않습니다. 왜?

글쎄, 입력할 때 일어나는 일은 터미널이 어떤 모드에 있는지에 따라 다릅니다. 대략적으로 말하자면, 터미널 자체가 기본 줄 편집(백스페이스가 처리됨)을 제공하는 일반적인 "요리된" 모드 또는 모든 키 입력이 응용 프로그램으로 들어가고 응용 프로그램이 이를 처리하는 방법을 결정하는 "원시" 모드일 수 있습니다. 그들과 이에 대한 응답으로 출력되는 내용. Cooked 모드는 일반적으로 "local echo"와 함께 사용됩니다. 여기서 터미널(사용자에게 로컬)은 문자가 입력되는 대로 인쇄됩니다. 원시 모드에서 응용 프로그램은 일반적으로 입력된 문자를 에코하여 표시되는 내용을 완전히 제어합니다.

터미널 모드에 대한 설명은 다음 질문을 참조하세요. "원시" 장치 드라이버와 "요리된" 장치 드라이버의 차이점은 무엇입니까?

예를 들어 를 실행하면 cat터미널은 베이킹 모드(기본값)가 되어 라인 편집을 처리합니다. 예를 들어 클릭하면 빈 입력만 xBackspaceCtrl-D읽혀 cat입력이 끝났음을 나타냅니다. 를 사용하여 이를 확인할 수 있습니다 strace. 그러나 대화형 Bash 셸을 실행하면 백스페이스 키를 자체적으로 처리하고 사용자가 기대하는 문자 지우기에 적합하다고 판단되는 내용을 출력합니다.


strace -etrace=read,write -obash.trace bash위 시퀀스를 입력한 후 출력의 일부는 다음과 같습니다 xBackspaceCtrl-D.

read(0, "x", 1)                         = 1
write(2, "x", 1)                        = 1
read(0, "\177", 1)                      = 1
write(2, "\10\33[K", 4)                 = 4
read(0, "\4", 1)                        = 1

먼저 Bash를 수행 read하고 터미널에 write출력합니다 . 그런 다음 백스페이스 문자(8진수 문자 코드 0177 또는 10진수 문자 코드 127)를 읽고 커서를 뒤로 이동하여 x백스페이스 문자(8진수 010, 10진수 8 (*) )를 출력합니다.그리고산출제어 순서줄 끝을 지우는 데 사용됩니다 <ESC>[K. 마지막 것은 Bash가 프로그램을 종료하는 데 사용됩니다 \4.Ctrl-D

(* 입력에는 Ctrl-H10진수 문자 코드 8이 있습니다. 백스페이스는 터미널 설정 방법에 따라 여기 또는 127과 동일합니다.)

대조적으로, 동일한 실험에서는 cat"파일 끝" 조건인 0바이트의 단일 읽기만 표시됩니다. 파일 끝은 연결된 파이프나 소켓이 닫혔거나, 실제 파일 끝이거나, Ctrl-D베이크 모드에서 터미널로부터 수신되었음을 의미할 수 있습니다.

read(0, "", 131072)                     = 0

특히, 백스페이스 또는 에 대한 실제 코드는 cat볼 수 없으며 터미널에서 처리됩니다. 이는 커널의 가상 터미널 드라이버일 수도 있고, 직렬 연결 등을 통한 실제 물리적 터미널일 수도 있고, 동일한 시스템이나 SSH 연결의 원격 측에서 실행되는 xterm과 같은 터미널 에뮬레이터일 수도 있습니다. 사용자 공간 소프트웨어에는 중요하지 않습니다.xCtrl-D

답변2

코드( \b\n)은 텍스트가 아닌 커서를 이동합니다.

텔레타이프, 골프공 프린터 등에서 굵은 글꼴이나 취소선과 같은 놀라운 효과를 얻기 위해 프린터에서 커서를 조작해야 했던 "좋은 옛날"에서 이러한 동작이 유래했다는 것을 알게 될 것입니다.

\b삽입 지점을 뒤로 이동하면 덮어쓰기가 가능해집니다. 디지털 화면에서는 이전 내용이 지워지지만 오래된 프린터에서는 덮어쓴 문자가 나타납니다.

\n커서를 새 줄로 이동하지만 이전 줄의 텍스트는 뒤에 둡니다. 이는 커서를 줄의 시작 부분에 다시 놓고 프린터에 한 줄 위로 스크롤하도록 지시하는 CRLF입니다.

이것CR, LF 및 CRLF 코드이러한 새로운 효과를 달성하기 위해 오래된 장비를 조작해야 할 필요성과도 관련이 있습니다.

.....그리고 인쇄된 페이지에서 문자를 제거할 수 있는 방법은 없습니다. 인쇄용으로 게시하기 직전에 문자를 제거해야 합니다.

편집하다

2번 항목에 답해 주세요. 입력과 출력은 사용자가 지시하기 때문에 서로 다른 작업을 수행합니다.

\b삭제가 아닌 INSERT를 닫는 왼쪽 화살표와 동일합니다.

\nEnter 키가 아닌 아래쪽 화살표(LF) 및 HOME(CR)과 동일합니다.

답변3

우선, 이러한 것들에 대해 알고 싶다면 다음을 읽어야 합니다.

물어,

...뭔가를 입력한 다음 백스페이스를 누르면 마지막 문자가 삭제되지만 출력은 삭제되지 않습니다. 왜?

다음은 여러분을 위한 몇 가지 상식입니다. Unix 초기(Linux가 존재하기 전인 1970년대)에는 백스페이스 키 1 아니요입력한 문자를 삭제하면 사용자가 싫어합니다. 를 입력하고 beast백스페이스를 세 번 누르면 여전히 악마의 눈이 be|ast당신을 쳐다보고 있습니다( |커서를 나타냄). 입력한 후에도 st(항상 을 원했기 때문에 best) 화면이 계속 표시되어 best|t혼란스럽습니다.

BackspaceSpaceBackspace 많은 사용자는 문자를 공백으로 대체/파괴하기 위해(예: 수동으로) 입력 습관을 개발합니다. 삭제그들을. 결국(1979년 또는 1980년대 초) 개발자들은 마음을 누그러뜨리고 이를 자동으로 만들었습니다.

백스페이스를 누르면 커널 tty 줄 규칙은 (간단한 경우) Ctrl-H, 공백, 그리고 또 다른 Ctrl-H를 인쇄하여 이전 문자를 지웁니다.
원천:텍스트를 입력하는 동안 백스페이스를 누르면 Unix에서 내용을 삭제하는 방법

여기서 "Ctrl-H"는 백스페이스 키의 제어 코드입니다.

어떤 경우에는 이 옵션을 끄고 stty -echoe ( echoe = "echo" 및-"이러지 마세요"라는 뜻).
____
1 사실 초기에는 백스페이스 키가 백스페이스가 아니었지만 그건 또 다른 이야기입니다.

관련 정보