[unix] 터미널에서 줄 바꿈없이 4k 이상의 입력을 읽는 방법은 무엇입니까?

그래서 클립 보드에 새로운 라인 이없는 많은 데이터가 있습니다 (한 줄에 큰 SVG 파일입니다). 나는 갔다

$ cat >file.svg

그런 다음 (Gnome Terminal에서) 붙여 넣기를 시도했지만 처음 4kB 문자 만 허용되었습니다.

이것이 readline 기능 / 제한이라고 가정합니다.

이 문제를 피할 수있는 STDIN에서 읽을 수있는 방법이 있습니까?

편집하다

테스트 사례 : 데모 파일을 만듭니다. 이것은 ~ 4k “=”기호와 “foo bar”를 갖습니다.

{ printf '=%.0s' {1..4095} ; echo "foo bar" ; } > test.in

클립 보드에 복사

xclip test.in

(중간 클릭하여 삽입하려는 경우) 또는

xclip -selection clipboard test.in

(Ctrl-Shift-Insert를 사용하여 붙여 넣으려면)

그런 다음 cat >test.out붙여 넣습니다 (어느 쪽이든). 스트림을 종료하려면 Ctrl-D를 누르십시오. cat test.out– “foo bar”가 보입니까?

붙여 넣을 때 내 설정 (Ubuntu 12.04, Gnome Terminal, zsh)에서 만 볼 수 =있고 보이지 않습니다 foo bar. 검사 할 때도 동일합니다 test.out.



답변

소스를 올바르게 이해하면 Linux에서 터미널에서 한 번에 읽을 수있는 최대 문자 수 N_TTY_BUF_SIZE는 커널 소스에 의해 결정됩니다 . 값은 4096입니다.

이것은 터미널 인터페이스, 특히 정식 ( “요리 된”) 모드 의 한계로, 매우 조잡한 라인 편집기를 제공합니다 ( 파일 끝 행 시작시 백 스페이스, Enter, Ctrl+ D). 그것은 읽고있는 프로세스 외부에서 발생합니다.

터미널을 원시 모드로 전환하여 라인 처리를 비활성화 할 수 있습니다. 또한 Ctrl+ D및 기타 기능을 비활성화 하여 프로그램에 추가 부담을줍니다.

이것은 동기 부여가 거의 없기 때문에 수정되지 않은 고대 유닉스 제한입니다. 인간은 그런 긴 줄에 들어 가지 않습니다. 프로그램에서 입력을 공급하는 경우 파일 또는 파이프에서 프로그램 입력을 리디렉션합니다.

예를 들어 X 클립 보드의 내용을 사용하려면 xsel또는 에서 파이프하십시오 xclip. 귀하의 경우 :

xsel -b >file.svg
xclip -selection clipboard >file.svg

클립 보드 대신 X 선택 항목 (마우스로 강조 표시 한 설정)을 제거 -b하거나 -selection clipboard사용하십시오.

OSX에서는 pbpaste클립 보드 내용을 붙여넣고 pbcopy설정하는 데 사용하십시오.

ssh -X(일부 서버에서는 금지 할 수 있음) 을 사용하여 X11 전달을 활성화하면 SSH를 통해 X 클립 보드에 액세스 할 수 있습니다 . 만 사용할 수있는 경우 sshX11 포워딩하지 않고, 당신이 사용할 수있는 scp, sftp또는 sshfs파일을 복사 할 수 있습니다.

클립 보드를 전달할 수 없거나 붙여 넣기를 할 수는 없지만 가상 머신에 입력하는 것을 방지 할 수 있기 때문에 붙여 넣기가 유일한 솔루션 인 경우 대체 방법은 데이터를 줄 바꿈이있는 것으로 인코딩하는 것입니다. Base64 는 이에 적합합니다. 임의의 데이터를 인쇄 가능한 문자로 변환하고 디코딩 할 때 공백을 무시합니다. 이 접근 방식은 입력시 임의의 데이터를 지원하고 붙여 넣을 때 터미널이 해석 할 제어 문자도 추가한다는 이점이 있습니다. 귀하의 경우 콘텐츠를 인코딩 할 수 있습니다.

xsel -b | base64 | xsel -b

그런 다음 해독하십시오.

base64 -d
 Paste
Ctrl+D


답변

당신이로 실행중인 한계가있는 행의 최대 크기입니다 정규 입력 모드 , MAX_CANON.

표준 입력 모드에서 tty 드라이버는 기본 라인 편집 서비스를 제공하므로 사용자 공간 프로그램이 필요하지 않습니다. readline만큼 많은 기능을 가지고 있지는 않지만 삭제 (일반적으로 Backspace 또는 Delete) 및 kill (보통 Ctrl-U)과 같은 구성 가능한 특수 문자를 인식합니다.

귀하의 질문에 가장 중요한 것은 라인 끝 문자가 보일 때까지 표준 모드 버퍼 입력입니다. 버퍼는 tty 드라이버, 커널 메모리에 있기 때문에 크지 않습니다.

stty cbreak또는로 표준 모드를 ​​끈 stty -icanon다음 붙여 넣기를 수행 할 수 있습니다. 이것은 Ctrl-D로 EOF를 보낼 수 없다는 중요한 단점이 있습니다. 이것이 표준 모드가 담당하는 또 다른 것입니다. cat신호 생성 문자는 별도의 플래그 ( stty raw또는 stty -isig) 로 제어되므로 Ctrl-C를 사용 하여 계속 종료 할 수 있습니다 .

나에게 신비 왜, 당신은 이미 당신에 대해 알고있는 것을 증명 한 이후이다 xclip, 당신은 그냥 사용하지 않는 xclip -o > file의 대신cat


답변

당신이 할 경우 :

stty eol =

다음에 제시된 데모 실행 편집을 , 당신은 볼 수 foo는 바 의 출력에 test.out . 터미널의 라인 원칙은 입력에서 각 특수 eol 문자를 읽을 때 출력을 리더로 플러시합니다 .

Linux 표준 모드 터미널 은 다음과 같은 특수 입력 문자를 처리 stty icanon하거나 구성 할 수 있습니다 stty sane.

  • eof
    • 태만: ^D
    • 입력 라인을 종료하고 출력을 리더로 플러시합니다. 입력에서 제거되므로 행에서 유일한 문자로 입력되면 읽기 또는 파일 끝으로 리더에 전달됩니다.
  • ol
    • 기본값 : 할당되지 않은
    • 또한 입력 라인을 종료하지만 입력에서 제거되지는 않습니다.
  • 죽이다
    • 태만: ^U
    • 버퍼링 된 모든 입력을 지 웁니다.
  • 삭제
    • 기본값 : ^H (또는 가능 @하거나 ^?일부 시스템에서)
    • 마지막으로 버퍼링 된 입력 문자를 지 웁니다.

iexten가 도 설정 -처럼에게 stty icanon iexten또는, 다시, 아마 stty sane, 정식 리눅스 터미널도 처리 할 …

  • eol2
    • 기본 : 할당되지 않은
    • 또한, 또한 , 입력 라인을 종료하고, 또한 입력에서 제거되지.
  • 웨 라세
    • 태만: ^W
    • 마지막으로 버퍼링 된 입력 단어를 지 웁니다 .
  • rprnt
    • 태만: ^R
    • 버퍼링 된 모든 입력을 재 인쇄합니다.
  • 다음
    • 태만: ^V
    • 라인 제어가 바로 뒤 따르는 입력 문자에 관한 한 특별한 의미를 제거합니다.

이러한 문자는 입력 스트림에서 제거하고 ( eoleol2 제외) , 즉 처리 된 스트림을 리더로 전달하기 전에 연관된 특수 기능을 수행합니다 (일반적으로 쉘이지만 포 그라운드 프로세스 그룹이 될 수 있음). .

유사하게 처리되지만 임의의 icanon 설정과 독립적으로 구성 할 수있는 다른 특수 입력 문자 는 isig 세트 stty isig를 포함하며 아마도 제정신 구성 에도 포함될 수 있습니다.

  • 떠나다
    • 태만: ^\
    • 버퍼링 된 모든 입력을 플러시하고 ( noflsh 가 설정되지 않은 경우 ) SIGQUIT를 포 그라운드 프로세스 그룹으로 보냅니다. 코어 덤프가 생성 될 수 있습니다.
  • 서스펜션
    • 태만: ^Z
    • 버퍼링 된 모든 입력을 플러시하고 ( noflsh 가 설정되지 않은 경우 ) SIGTSTP를 포 그라운드 프로세스 그룹으로 보냅니다. 일시 중단 된 프로세스 그룹은 가능성 중 하나를 사용하여 다시 시작할 수 있습니다 kill -CONT "$!"하거나 fgA의 ( set -m) 작업 제어 쉘.
  • intr
    • 태만: ^C
    • 버퍼링 된 모든 입력을 플러시하고 ( noflsh 가 설정되지 않은 경우 ) SIGINT를 포 그라운드 프로세스 그룹으로 보냅니다.

그리고 IXON의 세트 – 같은 구성 stty ixon도 보통에 포함 제정신의 설정 :

  • 중지
    • 태만: ^S
    • 입력에서 시작 을 읽을 때까지 또는 ixany 가 설정되어 있을 때 하나 이상의 문자를 읽을 때까지 리더에 대한 모든 출력을 중지합니다 .
  • 스타트
    • 태만: ^Q
    • stop으로 이전에 중지 된 경우 출력을 다시 시작합니다 .
  • 처리시 중지시작 이 모두 입력에서 제거되지만 ixany 가 설정 될 때 입력 문자로 인해 출력이 다시 시작되면 해당 문자가 제거되지 않습니다.

Linux 이외의 다른 시스템에서 처리되는 특수 문자에는 다음이 포함될 수 있습니다.

  • 플러시
    • 태만: ^O
    • 버퍼링 된 입력의 삭제 및 플러시를 토글하고 입력에서 제거됩니다.
  • dsusp
    • 기본 : 할당되지 않은
    • 리더가 지정된 특수 입력 문자를 읽은 다음 SIGTSTP를 보낼 때만 버퍼링 된 모든 입력을 플러시합니다.

그리고 아마도 …

  • swtch
    • 기본값 ^@ ( \0또는 의미 NUL)
    • 포 그라운드 쉘 레이어를 전환합니다. 일부 시스템 에서 shl 쉘 계층 응용 프로그램 과 함께 사용 합니다.
    • 의 구현 shl멀티 플렉스의 ptys 및 작업 제어가 아닌 원래의 구현의과 호환되는 에서 swtch 의존 동작은 자유롭게에서 가지게 될 수있다 heirloom-toolchest툴 스위트.

이러한 입력 기능을 처리 하는 방법과 이유 (및 어쩌면 왜 그렇지 않은지)에 대한 명확한 그림을 보려면를 참조하십시오 man 3 termios.

적용 가능한 경우 위의 모든 기능을 할당 (또는 재 할당) 할 수 있습니다 sttyfunction assigned-key. 단일 기능을 비활성화하려면을 수행하십시오 . GNU, AST, 또는 가보의 모든과 상기 라인 편집의 모든 기능에 대한 과제와 다양한 시도로 또는 구현을 표시하는 것, 당신은 또한 수 로 NUL의 모든 기능에 대한 할당으로 설정 동일시하는 것 같다 할당되지 않은 내 리눅스에 체계.sttyfunction^-sttysttyfunction^@

아마 당신이 입력 할 때이 문자 들의 에코 를 보았을 것입니다 ( [-] ctlecho 로 구성 될 수 있습니다 ) . 그러나 이것은 당신이 어디에서했는지 보여주기위한 마커 일뿐입니다-입력을받는 프로그램은 그것들을 입력하고 ( 즉, eol [2] 제외 ) , 선 분야가 효과를 적용한 입력 사본 만받습니다.

터미널이 다양한 라인 편집 기능을 처리 한 결과, 사용자가 지시 한 기능을 수행하기 위해 입력을 어느 정도 버퍼링해야하므로 입력의 무한한 공급이 불가능합니다. 당신은 언제든지 죽일 수 있습니다. 라인 버퍼는 더 정확하게이다 버퍼입니다.

당신은 설정하면 EOL 또는 EOL2 둘 줄 바꿈 또는 리턴 문자, 예를 들면없는 경우에도 – – 당신은 할 수있을 것입니다 입력에서 발생하는 일부 구분 문자 죽일 가 마지막으로 발생하는 시점까지가 당신의 버퍼 이 중 다음 줄 또는 개행 (또는 icrnl 이 설정되고 igncr설정 되지 않은 경우 리턴 ) 까지 입력에서 입력 될 때까지 확장됩니다 .


답변

cat예를 들어 목격 할 수있는 것처럼 많은 수의 문자를 허용합니다 cat /dev/random > test.bin(중지하는 방법을 모르면 수행하지 마십시오 :). 큰 파일 을 복사하여 붙여 넣으려고 했습니다 cat > test.txt. Ctrlc또는 Ctrl-로 취소했는지 여부에 관계없이 모든 줄이 파일 d에 들어 갔지만 전자의 경우 모든 줄이 터미널에 인쇄 된 것은 아닙니다 . 이것은 cat인쇄를 버퍼링하여 텍스트의 전체 버퍼를 기다리거나 각 인쇄 전에 터미널에서 직접 입력하기 때문입니다.

필자의 시스템에서는 버퍼 크기는 4096 (2 ^ 12) 바이트 생각 : 사용하여 4095 바이트의 파일을 작성 (printf '1234567890%.0s' {1..409} && printf 12345) > test.in복사본으로 사용하여 버퍼 것으로, 부하를 xclip test.in시작 cat > test.out사용하여 붙여 넣기 ShiftInsert,를 눌러 스트림을 종료 Ctrld. 이제를 사용하여 바이트를 추가 printf '6' >> test.in하면 스트림이 두 번 인쇄 됩니다 . cat출력 (한 4096 바이트)에 도달하면 종료 후 쉘 에서 마지막 4095 바이트를 다시 입력 합니다.


답변

해결책은 vim과 같이 긴 줄을 지원하는 편집기에 붙여 넣는 것입니다.

vim을 사용하는 경우 텍스트를 :paste삽입 i하고 붙여 넣기 모드로 들어가기 전에 먼저 붙여 넣기 모드로 들어가십시오 .


답변