Enter 키가 EOL을 보내지 않는 이유는 무엇입니까?

Enter 키가 EOL을 보내지 않는 이유는 무엇입니까?

Unix/Linux EOL은 LF, 개행, ASCII 10, 이스케이프 시퀀스입니다 \n.

다음은 정확히 한 번의 키 누르기를 위한 Python 코드 조각입니다.

import sys, tty, termios
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
    tty.setraw(sys.stdin.fileno())
    ch = sys.stdin.read(1)
finally:
    termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
    return ch

Enter이 코드 조각에 대한 응답으로 키보드를 누르면 \r캐리지 리턴, ASCII 13이 표시됩니다.

존재하다윈도우, EnterSend CR LF == 13 10. *nix는 Windows가 아닙니다. 왜 Enter10이 아닌 13을 제공합니까?

답변1

본질적으로 "수동 타자기가 출현한 이래로 그렇게 되어 왔기 때문입니다." 진짜.

수동 타자기에는운송용지가 공급되고 입력할 때 앞으로 이동하며(스프링이 장착됨) 캐리지를 해제하는 레버나 키가 있어 스프링이 캐리지를 왼쪽 여백으로 되돌릴 수 있습니다.

전자 데이터 입력(전신 타자기 등)이 도입되면서 그들은 또한 이를 추진했습니다. 이러한 이유로 Enter많은 터미널의 키에는 이라는 라벨이 붙어 있습니다 Return.

캐리지를 왼쪽 여백으로 되돌린 후 줄바꿈이 발생합니다(수동 프로세스 중). 다시 말하지만, 전자 장치는 개별 line-feed작동을 위해 수동 장치를 모방합니다.

두 작업 모두 코드화되어(텔레타자기가 종이 유형을 생성하는 독립 실행형 장치 이상이 될 수 있도록) CR(캐리지 리턴) 및 LF(줄 바꿈)이 있습니다. 이 사진은ASR 33 텔레타이프 정보키보드를 Return오른쪽, Line-Feed왼쪽에 표시합니다. 그것은에있다옳은, 이는 기본 키입니다.

여기에 이미지 설명을 입력하세요.

그런 다음 유닉스가 나타났습니다. 개발자는 내용을 단축하는 것을 좋아합니다("생성된" 모든 약어를 살펴보세요 creat). 잠재적으로 두 부분으로 구성된 프로세스에 직면하여 그들은 개행 문자 앞에 캐리지 리턴이 있는 경우에만 의미가 있다고 결정했습니다. 그래서 그들은 명시적인 캐리지 리턴 문자를 삭제했습니다.문서, 터미널의 Return키 입력을 변환하여 해당 줄 바꿈을 보냅니다. 혼동을 피하기 위해 줄 바꿈을 "줄 바꿈"이라고 합니다.

터미널에 텍스트를 쓸 때 Unix는 반대 변환을 수행합니다. 줄 바꿈은 캐리지 리턴/줄 바꿈이 됩니다.

(예: "일반": 번역을 수행하지 않는 "원시" 모드와 반대되는 소위 "요리 모드").

요약:

  • 캐리지 리턴/라인 피드 순서는 13 10입니다.
  • 이것장비13개를 보내세요(네 말로는 '영원'이니까)
  • 유닉스 계열 시스템변화13 10 까지
  • 다른 시스템은 반드시 10개만 저장할 필요는 없습니다(Windows는 기본적으로 호환성이 얼마나 중요한지에 따라 10 또는 13 10만 허용합니다).

답변2

하지만토마스 디키의 답변맞습니다. Stéphane Chazelas는 Dickey의 답변에 대한 논평에서 전환이 확정된 것이 아니라 라인 규율의 일부라고 올바르게 언급했습니다.

실제로 번역은 완전히 프로그래밍 가능합니다.

이것남자 3 용어매뉴얼 페이지에는 기본적으로 모든 관련 정보가 포함되어 있습니다. (이 링크에는Linux 매뉴얼 페이지 프로젝트, Linux 전용 기능과 POSIX 또는 기타 시스템에 공통적인 기능을 항상 확인합니다.준수하다각 페이지의 섹션. )

터미널 iflag속성 ( old_settings[0]질문에 표시된 코드에서파이썬)에는 모든 POSIXy 시스템에 세 가지 관련 플래그가 있습니다.

  • INLCR: 설정된 경우 입력 시 NL을 CR로 변환합니다.
  • ICRNL: 설정한 경우( IGNCR설정하지 않은 경우) 입력 시 CR을 NL로 변환합니다.
  • IGNCR: 입력 시 CR 무시

마찬가지로 관련 출력 설정( )이 있습니다 old_settings[1].

  • OPOST: 출력 처리를 활성화합니다.
  • OCRNL: 출력에서 ​​CR을 NL에 매핑합니다.
  • ONLCR: 출력에서 ​​NL을 CR로 매핑합니다. (XSI; 모든 POSIX 또는 단일 Unix 사양 시스템에 적용되지는 않습니다.)
  • ONOCR: 첫 번째 열의 CR을 건너뜁니다(출력하지 않음).
  • ONLRET: CR을 건너뜁니다(출력하지 않음).

예를 들어, 이 tty모듈에 의존하지 않을 수 있습니다. "makeraw" 작업은 단순히 플래그 집합(및 oflag 집합 CS8)을 지웁니다.

import sys
import termios

fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
ch = None

try:
    new_settings = termios.tcgetattr(fd)
    new_settings[0] = new_settings[0] & ~termios.IGNBRK
    new_settings[0] = new_settings[0] & ~termios.BRKINT
    new_settings[0] = new_settings[0] & ~termios.PARMRK
    new_settings[0] = new_settings[0] & ~termios.ISTRIP
    new_settings[0] = new_settings[0] & ~termios.INLCR
    new_settings[0] = new_settings[0] & ~termios.IGNCR
    new_settings[0] = new_settings[0] & ~termios.ICRNL
    new_settings[0] = new_settings[0] & ~termios.IXON
    new_settings[1] = new_settings[1] & ~termios.OPOST
    new_settings[2] = new_settings[2] & ~termios.CSIZE
    new_settings[2] = new_settings[2] | termios.CS8
    new_settings[2] = new_settings[2] & ~termios.PARENB
    new_settings[3] = new_settings[3] & ~termios.ECHO
    new_settings[3] = new_settings[3] & ~termios.ECHONL
    new_settings[3] = new_settings[3] & ~termios.ICANON
    new_settings[3] = new_settings[3] & ~termios.ISIG
    new_settings[3] = new_settings[3] & ~termios.IEXTEN
    termios.tcsetattr(fd, termios.TCSANOW, new_settings)
finally:
    termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)

return ch

호환성상의 이유로 먼저 이러한 모든 상수가 termios 모듈에 존재하는지 확인하고 싶을 수도 있습니다(POSIX가 아닌 시스템에서 실행 중인 경우). 처리할 데이터가 없는 경우 읽기를 차단할지 여부와 차단 기간(10초 단위의 정수)을 설정하려면 new_settings[6][termios.VMIN]및 를 사용할 수도 있습니다 . new_settings[6][termios.VTIME](읽기가 즉시 반환되어야 하는 경우 일반적으로 VMIN0으로 설정되거나 VTIME읽기가 최대 기다려야 하는 시간에 대한 양수(10분의 1초)로 설정됩니다.)

보시다시피, 위(및 일반적으로 "makeraw")는 입력에 대한 모든 번역을 비활성화합니다. 이는 고양이가 보고 있는 동작을 설명합니다.

    new_settings[0] = new_settings[0] & ~termios.INLCR
    new_settings[0] = new_settings[0] & ~termios.ICRNL
    new_settings[0] = new_settings[0] & ~termios.IGNCR

정상적인 동작을 얻으려면 이 세 가지를 지우는 행을 생략하면 됩니다. 입력 번역은 "원본"이더라도 변경되지 않습니다.

new_settings[1] = new_settings[1] & ~termios.OPOST이 줄은 다른 출력 플래그에 관계없이 모든 출력 처리를 비활성화합니다. 출력 처리를 그대로 유지하려면 이를 무시할 수 있습니다. 이는 원시 모드에서도 출력을 "정상"으로 유지합니다. (입력이 자동으로 에코되는지 여부에는 영향을 미치지 않습니다. 이는 cflag ECHOin new_settings[3].)

마지막으로 새 속성을 설정할 때 다음 조건이 충족되면 호출이 성공합니다.어느에 대한 새로운 설정이 설정되었습니다. 설정이 민감한 경우(예: 명령줄에서 비밀번호를 요청하는 경우) 새 설정을 가져와 중요한 플래그가 올바르게 설정/설정 해제되었는지 확인해야 합니다.

현재 터미널 설정을 보려면 다음을 실행하십시오.

stty -a

입력 플래그는 일반적으로 네 번째 줄에 있고 출력 플래그는 다섯 번째 줄에 있습니다. -플래그가 설정되지 않은 경우 플래그 이름이 플래그 이름 앞에 추가됩니다. 예를 들어, 출력은 다음과 같을 수 있습니다.

speed 38400 baud; rows 58; columns 205; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = M-^?; eol2 = M-^?; swtch = M-^?; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; flush = ^O; min = 1; time = 0;
-parenb -parodd cs8 hupcl -cstopb cread -clocal -crtscts
-ignbrk brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff -iuclc ixany imaxbel iutf8
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl echoke

의사 터미널 및 USB TTY 장치에서는 전송 속도가 중요하지 않습니다.

비밀번호 등을 읽으려는 Bash 스크립트를 작성하는 경우 다음 관용어를 고려하십시오.

#!/bin/bash
trap 'stty sane ; stty '"$(stty -g)" EXIT
stty -echo -echonl -imaxbel -isig -icanon min 1 time 0

EXIT트랩은 쉘이 종료될 때마다 실행됩니다. stty -g스크립트가 시작될 때 터미널의 현재 설정을 읽어 스크립트가 종료될 때 현재 설정이 자동으로 복원되도록 합니다. Ctrl+interrupt 스크립트를 사용하면 C올바른 작업을 수행할 수도 있습니다. (신호가 있는 일부 특수한 경우에는 터미널이 원래/비정규 설정에서 멈추는 경우가 있었지만( reset터미널에 +를 맹목적으로 입력해야 함) 실제 원래 설정을 복원하기 전에 실행하면 매번 문제가 해결되었습니다. 왜 존재하는 이유 ;)Enterstty sane

내장된 bash를 사용하여 (터미널에 에코하지 않고) 입력 줄을 읽 read거나 다음을 사용하여 입력 문자를 문자별로 읽을 수도 있습니다.

IFS=$'\0'
input=""
while read -N 1 c ; do
    [[ "$c" == "" || "$c" == $'\n' || "$c" == $'\r' ]] && break
    input="$input$c"
done

IFSASCII NUL로 설정되지 않은 경우 read내장 기능은 구분 기호를 사용하므로 c비어 있게 됩니다. 어린 선수들에게 함정.

관련 정보