如何将字符串推送到标准输入?在启动时通过stdin提供输入,然后以交互方式读取stdin输入

时间:2015-03-27 02:13:17

标签: linux bash stdin interactive

有没有办法在调用时将字符串“推”到程序的stdin流?

这样我们就会有

的效果
echo "something" | ./my_program

但不是在"something"之后读取EOF,my_program将从原始标准输入(例如键盘)读取其进一步输入。

示例:假设我们要启动一个bash shell,但我们要在其中做的第一件事就是调用dateecho date | bash无法完成这项工作,因为shell会在运行date之后终止。

2 个答案:

答案 0 :(得分:9)

这可能有效:

(echo "something"; cat -) | ./my_program

它创建了一个子shell,其中第一行输出来自echo,其余来自cat的标准输入,这是终端(或脚本的标准输入,任何一个)率)。我使用-来强调从标准输入中读取需要cat - 我不会忘记在"$@"命令之后忘记指定cat或其他内容。省略-并没有产生差异;它可能会产生可理解性差异。

请注意,my_program的输入不再是终端,而是连接到终端的管道,这会影响程序的行为。 cat流程也会引入延迟。

期望

如果这不起作用,那么您可能需要使用expect。这是用于脚本与其他程序交互的通用工具,它使用伪ttys(ptys)使其看起来好像终端的用户正在与其他程序通信。 作为anishsane notesexpect有一个interact命令,可以用来让用户在一些固定的前导后输入程序。

当心

将其与第二种情况相匹配并不是一种舒适的体验:

(echo date; cat -) | bash -i

-i告诉Bash它是一个交互式shell。 date工作了,我得到了一个提示,但我没有再执行任何命令。中断给了我更多的提示;几乎其他一切似乎都被忽略了。这可能是cat对其输出进行过多缓冲。

我最终从另一个终端窗口杀了那个shell。我好运:

(echo date; cat -) | bash

但是Bash没有提示。小心;确保你知道如何摆脱困境。

I / O重定向特技

ricipointed out在这种特殊情况下,您可以使用:

{ { echo date; echo 'exec 0<&3-';} | bash -i; } 3<&0

这很聪明,因为尾随3<&0在描述符3上复制了原始标准输入(文件描述符0),然后运行bash -i,其输入来自两个echo声明。第一个请求日期。第二个重新重定向事物,以便标准输入现在来自文件描述符3(即0<&3部分) - 这是原始标准输入,也就是'终端' - 并关闭文件描述符3(这是尾随-;它是POSIX shell Bash上的I/O redirection扩展名。)

答案 1 :(得分:1)

使用可能更简单但有限的替代补充Jonathan Leffler's helpful answer

如果

  • ./my_programbash,与OP的示例相同
  • 启动命令产生的副作用是可以接受的:
    • EITHER:保持打开的bash实例无法全部显示
    • OR:仅限于将所有已修改的变量继承为导出的变量

您可以尝试以下方法:

bash -c "$(<command that produces Bash commands>); exec bash -i"

使用date命令的示例作为启动命令:

bash -c "$(echo 'date'); exec bash -i"

执行date然后 new 实例替换正在运行的bash实例,然后保持打开状态 (由于既没有收到stdin输入也没有通过-c传递给它的命令)。

为了说明对 startup shell环境所做的任何更改都不会传播到最终保持打开的那个,请考虑以下事项:

bash -c "$(echo 'date; foo=bar; echo $foo'); exec bash -i"

这将打印日期并分配和打印变量$foo,但如果您再次执行echo $foo ,则不会定义它,因为 shell实例最终保持打开的状态不会从执行启动命令的状态继承其状态

您可以 部分解决此限制 -a传递给bash ,然后导致由启动命令修改或创建的所有变量 自动导出

bash -ac "$(echo 'date; foo=bar; echo $foo'); exec bash -i"

现在,如果您在保持打开的实例中再次执行echo $foo,它将打印bar

注意:

  • 这些变量实际上变成了 environment 变量,这意味着由stay-open shell创建的任何子进程也会看到它们。