以非交互方式向交互式程序传递参数

175

我有一个Bash脚本,使用read命令交互式地读取命令参数,例如是/否选项。 有没有一种方法可以在非交互脚本中调用此脚本并传递默认的选项值作为参数?

我不仅需要传递一个选项到交互式脚本中。


2
如果它正在从stdin读取,则可以将输入通过管道传入 - lc.
4
由于此问题有很多重复,值得指出的是,交互式程序使用哪种语言编写并不重要。它可以是一个读取标准输入的C程序,也可以是一个Erlang应用程序或其他任何东西。有些东西会从命令行运行并且需要繁琐地进行交互输入,你想自动化它。 - tripleee
当然,如果您可以控制那个讨厌的应用程序,最好重写它,使其能够通过配置文件、命令行选项或其他方式以非交互方式读取答案。这样更可靠、更稳健,可以防止交互式问题的顺序或措辞发生变化。 - tripleee
5个回答

209

许多方法

可以将您的输入导入管道中

echo "yes
no
maybe" | your_program

从文件进行重定向

your_program < answers.txt

使用Here Documents(这样可以使内容更易读)


your_program << ANSWERS
yes
no
maybe
ANSWERS
使用here string
your_program <<< $'yes\nno\nmaybe\n'

7
值得注意的是,这仅在程序读取标准输入时有效。有些程序会特意以交互方式读取例如密码之类的信息,即使标准输入是管道。对于密码来说,出于安全原因这是有意义的;尽管有些交互式程序只是设计得不好。 - tripleee
@tripleee 沿着你所说的方向,如何编写一个不受 stdin 影响的脚本来读取密码?我知道可以使用 read 命令来获取 stdin,但是你所描述的功能应该使用哪个函数实现呢? - flow2k
在这种情况下,您需要查看您尝试交互的程序是否有特殊的方法将输入发送到它(例如sshpass、ssh-agent),或者使用expect来脚本化交互。 - glenn jackman
2
像Expect这样的程序所做的是在伪终端下运行客户端,使客户端看起来好像另一端有一个具有终端和键盘的用户。你无法使用常规管道完成这个操作。 - tripleee
1
最好避免使用echo -e; 而是使用printf '%s\n' i 2 y y | your_command。将所有输入放在一行上显然只传递了一行输入,即用所有文本回答第一个提示。 - tripleee
显示剩余6条评论

64

对于更复杂的任务,可以使用expecthttp://en.wikipedia.org/wiki/Expect)。

它基本上模拟了一个用户,您可以编写脚本来响应特定程序输出和相关内容。

这在像ssh这样禁止通过管道输入密码的情况下也适用。


14
在SSH情况下,正确的解决方案是切换到公钥身份验证。 - tripleee

20

你可以将数据放入一个文件中,然后像这样重新定向它:

$ cat file.sh
#!/bin/bash

read x
read y
echo $x
echo $y

脚本的数据:

$ cat data.txt
2
3

执行脚本:

$ file.sh < data.txt
2
3

1
这就是答案,同时也告诉了如何处理来自任何来源的输入,完美。 - Muhammad Awais

17

只想再添加一种方法。在其他地方找到了它,而且非常简单。 假设我想要在命令行中为“execute_command”命令的所有提示都传递yes,那么我只需将yes导入即可。

yes | execute_command

这将使用“是”作为所有是/否提示的答案。


3
这也可以定制为不仅传递 y,而是任何您喜欢的字符串。例如,要传递 n,只需编写 yes n | execute_command - lupalby

11

您还可以使用printf将输入管道传输到脚本中。

var=val
printf "yes\nno\nmaybe\n$var\n" | ./your_script.sh

那就是救了我。谢谢 @spanchan。 - sk001
我不明白为什么,在某些程序(如wml)中使用printf可以正常工作,而其他技术都无法实现。 - Matthemattics

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接