4

我试图找到一种调用交互式命令行程序的方法,以便它直接从键盘和命名管道获取输入。我的目标是让它与 MATLAB 一起工作,但我认为 Bash 和一个例子一样好用。所以这个想法是启动 Bash,一旦它运行,我就可以输入命令,使用向上箭头查看历史记录等,还可以将命令发送到命名管道。几天来我一直在四处寻找和摆弄这个,但到目前为止我所尝试的一切都没有奏效。

例如,在https://serverfault.com/questions/171095/how-do-i-join-two-named-pipes-into-single-input-stream-in-linux有一个有用的线程建议做类似的事情这:

mkfifo alt_in
(tail -f alt_in & cat) | bash

这几乎正​​是我正在寻找的,除了如果您尝试使用退格键或箭头键,它就无法正常工作。(我想这是因为cat拦截击键,这通常由 bash 中的 readline 库处理?)还有其他建议吗?

最终我想有一种方法来启动一个 MATLAB 进程,这样我就可以从 TextMate 向它发送命令,但也可以在终端中与它进行交互。我在工作中使用 MATLAB,但不太喜欢它的 GUI 或编辑器。

编辑 2010 年 12 月 19 日

感谢所有非常有用的建议!我想为任何感兴趣的人总结一下这个结果。我调查了rlwrap,但由于我的目标是让它在任何人都可以使用的 TextMate 包中工作,所以我对依赖非标准实用程序(我应该首先提到的)犹豫不决。expect我也简单地检查了unbuffer一下,但是,好吧,它们看起来很复杂,我只是没有勇气去深入研究。

screen为此工作得很好 - 如下所示,我可以打开终端,开始screen,开始matlab -nodesktop,然后可以让 TextMate,例如,使用screen -X ...TextMate 命令将选定的文本发送到 Matlab。我注意到这种方法的缺点是:

  1. 发送超过 1,024 个字符的文本块会导致“屏幕”出错;我认为某处有一些缓冲区不能容纳更多,但没有花任何时间试图追踪它。
  2. 屏幕有自己的回滚缓冲区,使终端的滚动条毫无用处。也许有一个选项可以改变它的工作方式?
  3. Control-A 是 `screen` 的命令键击;除非您重新绑定命令键,否则您不能使用它移动到行首。

当我在玩 . 时screen,我突然想到,虽然我问的问题是关于连接管道和 STDIN 等等,但实际上我只关心一个非常具体的情况:从 TextMate 获取文本到终端。这促使我尝试使用 AppleScript 执行此操作,令人惊讶的是,结果证明它比我尝试过的任何其他事情都更简单、更健壮。创建一个 TextMate 命令,将选定的文本或当前行作为输入,并包含

#!/usr/bin/env osascript

set input_command to do shell script "cat"

tell application "Terminal"
    do script input_command in window 1
end tell

只要 MATLAB 在最前面的终端窗口中,效果就很好。(也可以搜索运行 MATLAB 的终端选项卡,为了清楚起见,我只是将其排除在外。)

这个故事的寓意是我应该问更具体的问题。再次感谢所有帮助;我从摔跤中学到了很多东西!

4

3 回答 3

2

试试这个:

mkfifo alt_in
(tail -f alt_in & rlwrap cat) | bash

您不会得到提示,但您可以输入命令和使用箭头键等,包括历史检索。您可以echo从另一个终端向命名管道发送命令,它们将在接收端执行,但它们不会出现在其历史记录中。

其他一些需要调查的事情:

  • 预计
  • 屏幕 -x 和屏幕 -X

对于后者,在一个终端开始screen。您将能够像往常一样在那里与 Bash 进行交互。现在在另一个终端上,做

screen -ls

确定screen您启动的会话的 PID。它将是一行开头的数字,如下所示:

31544.pts-2.hostname     (01/01/2010 01:01:01 PM)        (Attached)

现在您可以执行以下操作:

screen -S 31544 -X stuff $'echo Your ad here.\n'

这将导致echo命令在另一个终端上执行。导致其中$''的转义序列被解释,在这种情况下给我们一个换行符,以便我们可以“按下” Enter

假设我们这样做了:

screen -S 31544 -X stuff $'top\n'

现在top正在运行。我们可以去那个终端并按下q退出,但那有什么乐趣呢?

screen -S 31544 -X stuff 'q'

请注意,这次我们不需要换行符。

于 2010-11-25T07:19:56.083 回答
1

尝试将数据通过管道传输到unbuffer.

于 2010-11-25T06:23:08.357 回答
0

键盘输入有不同的风格,称为“原始模式”、“cbreak 模式”和“熟模式”。

原始模式是操作系统将您键入的每个按键传递给程序(例如 bash)。

熟模式是操作系统缓冲一行并允许您进行简单编辑(例如删除字符)的地方。当您按 RETURN 或 EOF(通常Ctrl-D)时,它将向程序发送一行。

stty 命令允许您定义许多键码,这些键码被解释为行尾 (RETURN)、EOF (Ctrl-D) 和其他一堆。

Cbreak 模式是一个中途站,其中许多控制字符保留了它们通常的功能,但操作系统仍然一次向应用程序发送一个字符。bash、vi 等程序一般都使用这种模式。

如果您将终端设置为原始模式,那么您将无法再使用键盘“突破”它,除非您正在运行的程序合作。

Expect (这里这里) 可以向 Bash 提供一个终端界面,因此它仍然认为它是从普通键盘运行的,并且仍然会执行我们习惯的所有酷炫的 bash 命令行编辑。

Expect 可以在原始模式和管道中读取来自键盘的输入并无缝传递。

于 2010-11-25T07:18:58.263 回答