파이프를 사용해도 tty 입력을 어떻게 활성화합니까?

파이프를 사용해도 tty 입력을 어떻게 활성화합니까?

tty 입력이 필요한 프로그램의 출력을 수정해야 합니다. 프로그램의 출력을 유틸리티(예: sed)로 파이프하면 입력 줄이 표시되지 않습니다.

구체적이고 간단한 예로 REPL 프롬프트가 포함된 일반 Scala 입력을 사용하고 싶습니다.

$ scala
Welcome to Scala 2.12.3 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_60).
Type in expressions for evaluation. Or try :help.

scala>

모든 항목을 Java다음으로 변경합니다 Mocha.

$ scala | sed 's/Java/Mocha/g'
Welcome to Scala 2.12.3 (Mocha HotSpot(TM) 64-Bit Server VM, Mocha 1.8.0_60).
Type in expressions for evaluation. Or try :help.

문제는 scala>마지막 줄( )과 입력한 키보드 입력이 를 누를 때까지 나타나지 않는다는 것입니다. [Enter]나는 두 번째 버전이 첫 번째 버전과 동일하게 작동하기를 원합니다. 단지 sed대체(물론 키보드 입력을 대체하는 것은 아닙니다)만 있습니다. 가능합니까?

(물론 휴대용 솔루션이 가장 좋지만, 유일한 솔루션이 셸이나 배포판 전용이라면 Zsh와 BSD를 선호합니다. 감사합니다.)

답변1

파이프로 인해 블록 기반 버퍼링이 사용될 수 있으므로 버퍼링이 문제가 됩니다 scala(기본 터미널 회선 기반 버퍼링 대신 참조).setvbuf(3)) 및 sed버퍼링(또는 파이프라인의 다른 항목)이 수행됩니다. stdbuf모든 것에 적용해보고 이식성을 버리고 원숭이 패치가 작동하기를 바랄 수도 있습니다 LD_PRELOAD. 또 다른 옵션은 PTY에서 REPL을 실행하고 사용자 입력을 제공하고 출력을 보내기 전에 바꾸는 것입니다. 여기에 표시된 SBCL은 scala내 컴퓨터에서 전혀 작동하지 않습니다.

$ ./mochanichize sbcl 
This is SBCL 1.3.20, an implementation of ANSI Common Lisp.
More information about SBCL is available at <http://www.sbcl.org/>.

SBCL is free software, provided as is, with absolutely no warranty.
It is mostly in the public domain; some portions are provided under
BSD-style licenses.  See the CREDITS and COPYING files in the
distribution for more information.
* (print "Java")

"Mocha" 
"Mocha"
* (exit)
$ 

그리고 코드 mochanichize.

#!/usr/bin/env expect

package require Tcl 8.5

proc mochanichize {fh} {
   global godot
   set somedata [read $fh]
   if {[eof $fh]} { close $fh; set godot 1; return; }
   regsub -all {\mJava\M} $somedata {Mocha} somedata
   puts -nonewline $somedata
}

proc sendtoprog {from to} {
   # TODO support ^D but that's more complicated
   puts -nonewline $to [read $from]
}

# no echo on PTY command we're running (soas not to duplicate what is
# echo'd back to the user via the user tty)
set stty_init -echo

if {[catch {spawn -noecho {*}$argv} err]} { puts stderr $err; exit 1 }

chan configure $spawn_id -blocking 0 -buffersize 1
chan event $spawn_id readable [list mochanichize $spawn_id]

chan configure stdin -blocking 0 -buffersize 1
chan configure stdout -blocking 0 -buffersize 1
chan event stdin readable [list sendtoprog stdin $spawn_id]

# TODO better handle ^Z this goes all meh on it
trap SIG_IGN SIGTSTP

vwait godot

관련 정보