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


19

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이 표시됩니다.

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


2 바이트를 읽으십시오 .
Michael Hampton

@MichaelHampton Nope, 1 바이트를 읽은 후에는 파일 디스크립터를 기다리는 것이 없습니다.
cat

답변:


11

하지만 토마스 당나귀의 대답은 매우 정확, 스테판 Chazelas가 올바르게 변환이 돌에 설정되어 있지 않은지 당나귀의 대답에 코멘트에서 언급; 그것은 선 분야의 일부입니다.

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

사람 3 termios의의 man 페이지는 기본적으로 모든 관련 정보가 들어 있습니다. (링크는 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 또는 Single-Unix-Specification 시스템에서 사용 가능하지는 않습니다.)
  • ONOCR: 첫 번째 열에서 CR을 건너 뜁니다 (출력하지 않음).
  • ONLRET: CR을 건너 뜁니다 (출력하지 않음).

예를 들어, tty모듈에 의존하지 않아도됩니다 . "makeraw"연산은 플래그 세트를 지우고 (오프 래그를 설정합니다 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 모듈에 먼저 존재하는지 확인하고 싶을 수도 있습니다 (POS가 아닌 시스템에서 실행하는 경우). 당신은 또한 사용할 수 있습니다 new_settings[6][termios.VMIN]new_settings[6][termios.VTIME]이 보류중인 데이터도없고, 시간 (0.1 초의 정수의) 경우 세트에 읽기가 차단할지 여부를 지정합니다. (일반적으로 VMIN0 으로 설정되며, VTIME읽기가 즉시 반환되어야하는 경우 또는 읽기가 최대 대기 시간을 양수 (10 초)로 설정합니다.)

보시다시피, 위의 (그리고 일반적으로 "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줄은 다른 출력 플래그가 무엇을 말하는지에 관계없이 모든 출력 처리를 비활성화합니다. 출력 처리를 그대로 유지하려면 생략 할 수 있습니다. 이것은 raw 모드에서도 출력을 "정상"으로 유지합니다. (입력이 자동으로 반향되는지 여부에 영향을 미치지 않으며,의 ECHOcflag에 의해 제어됩니다 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+로 스크립트를 중단 할 수도 C있으며 올바른 작업을 수행합니다. (신호가있는 일부 모퉁이의 경우 터미널이 때로는 원시 / 비정규 설정 ( 터미널에서 입력 reset+ Enter맹목적으로 설정해야 함 )으로 고정되어 있지만 stty sane실제 원래 설정을 복원하기 전에 실행 하면 매번 그래서 그것이 존재하는 이유입니다; 일종의 안전성이 추가되었습니다.)

readbash 내장을 사용하여 입력 행 (터미널에 대해 선택 취소)을 읽거나 문자를 사용하여 입력 문자를 읽을 수도 있습니다

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

IFSASCII NUL로 설정하지 않으면 read내장 기능이 분리 기호를 사용하므로 c비워집니다. 젊은 선수들을 위해 함정.


1
오, 신 '을 위해, 아무것도 없는 지금 :( 간단한
고양이

그것은 다른 하나가 큰 경우에도, 파이썬 dev에로 나에게 가장 도움이 있기 때문에 나는이 대답을 받아들이는거야
고양이

2
@ cat : 이것이 당신에게 가장 도움이 될 수는 있지만, 여전히 Thomas Dickey의 대답이 더 정확 하다고 말할 것 입니다. 차라리 당신은 대신 그것을 받아들이고 싶습니다.
공칭 동물

4
귀하의 +15 담당자를 기꺼이 포기할 의향이 있지만 크레딧을주는 것은 @cat입니다. 답변의 수락 여부는 게시 된 답변의 "가장 정확"하다는 표시는 없습니다. 그것은 단지 개인적인 이유가 무엇이든 OP가 선호하는 것을 의미합니다. "가장 올바른"것이 일반적으로 가장 높은 평가를받습니다. 답변을 수락하는 것은 개인 취향에 달려 있습니다. OP가 선호하는 경우 수락하지 않는 이유는 없습니다.
terdon

1
@terdon : 알았어, 그럼 내가 고쳤어.
공칭 동물

30

본질적으로 "수동 타자기 이후로 그렇게 되었기 때문"입니다. 정말.

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

전자 데이터 입력 (텔레타이프 등)이 도입됨에 따라이를 진전시켰다. 따라서 Enter많은 터미널 의 키에는 레이블이 붙어 Return있습니다.

캐리지를 왼쪽 여백으로 되 돌린 후 (수동 프로세스에서) 라인 피드가 발생했습니다. 다시, 전자 장치는 수동 장치를 모방하여 별도의 line-feed작업을 수행했습니다.

텔레타이프는 용지 유형을 생성하는 독립형 장치 이상이 될 수 있도록 두 작업이 모두 인코딩되므로 CR(캐리지 리턴) 및 LF(줄 바꿈)이 있습니다. ASR 33 Teletype Information 의이 이미지 Return는 오른쪽과 Line-Feed왼쪽 에 키보드를 보여줍니다 . 오른쪽 에있는 것은 주요 키였습니다.

여기에 이미지 설명을 입력하십시오

유닉스는 나중에 나왔습니다. 개발자들은 작업을 단축하기를 원했습니다 ( creat"생성"에 대한 모든 약어를 살펴보십시오 ). 두 부분으로 된 프로세스에 직면하여 라인 피드는 캐리지 리턴이 선행되는 경우에만 의미가 있다고 결정했습니다. 따라서 그들은 파일 에서 명시 적 캐리지 리턴을 삭제하고 Return해당 키를 전송하도록 터미널 키를 변환했습니다 . 혼란을 피하기 위해 줄 바꿈을 "줄 바꿈"이라고했습니다.

터미널에서 텍스트를 쓸 때 Unix는 다른 방향으로 번역합니다. 줄 바꿈은 캐리지 리턴 / 줄 바꿈이됩니다.

(즉, "일반적으로": 번역이 수행되지 않는 "원시"모드와 달리 소위 "요리 모드").

요약:

  • 캐리지 리턴 / 라인 피드는 시퀀스 13 10입니다.
  • 장치 ( "영원히"당신의 측면에서 이후) 13 전송
  • 유닉스 계열 시스템 은 13 10으로 변경
  • 다른 시스템은 반드시 10 만 저장하지 않아도됩니다 (Windows는 호환성의 정도에 따라 10 또는 13 10 만 수용합니다).

1
수동 타자기의 레버를 보여줄 멋진 그림을 찾았지만 저해상도 이미지 만 발견했습니다.
Thomas Dickey

3
그 중 하나를 입력해야한다면 모든 것을 줄여야합니다!
Michael Hampton

3
역사 부분에 관해서 : 내가 사용했던 수동 타자기는 이것 과 비슷하지만 하나의 레버 만 가지고 있습니다. 잡아 당기면 롤러를 먼저 크랭크 한 다음 캐리지를 당깁니다. 그리고 스프링을 당기는 것은이 끌어 당김이었습니다. 입력 된 각 문자 또는 탭을 누르면 스프링이 다소 풀려 캐리지가 "언로드 된"위치로 다시 이동합니다.
RealSkeptic

2
입력시 CR은 (tty 라인 원칙에 의해) CR LF가 아닌 LF로 변환됩니다. 로 변환되는 출력 (입력의 에코 포함) LFCR LF있습니다. 당신이 입력 할 때 foo<Return>조리 모드에서 응용 프로그램은 읽기 foo\nfoo\r\n단말기에 에코에 대한 제어 규칙에 의해 다시 전송됩니다.
Stéphane Chazelas

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.