即使使用管道,如何启用 tty 输入?

即使使用管道,如何启用 tty 输入?

我需要修改要求 tty 输入的程序的输出。当我将程序的输出通过管道传输到实用程序(例如,sed但是)时,不会显示输入行。

作为一个具体的简单示例:我想采用正常的 Scala 输入,其中包括 REPL 提示:

$ 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>

并将所有出现的 更改JavaMocha

$ 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>after 之前,最后一行 ( ) 和键入的任何键盘输入都不会显示。[Enter]我希望第二个版本的行为与第一个版本相同,只是进行sed替换(当然不是键盘输入的替换)。这可能吗?

(当然,便携式解决方案是最好的,但如果唯一的解决方案是特定于 shell 或发行版的,我最好喜欢 Zsh 和 BSD。谢谢。)

答案1

缓冲将是一个问题,因为scala可能由于管道而使用基于块的缓冲(而不是默认的基于终端行的缓冲,请参阅setvbuf(3))以及由sed(或管道中的其他任何内容)完成的缓冲。你可以尝试stdbuf在所有东西上拍打,抛开便携性,并祈祷那些LD_PRELOAD猴子补丁能起作用;另一种选择是在 PTY 下运行 REPL,向其提供用户输入,并在发送之前替换输出。这里显示 SBCLscala在我的机器上完全不起作用。

$ ./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

相关内容