文章目录
- 问题
- 回答
- 1. 使用 Here Document
- 2. 使用 echo 管道传递
- 3. 使用文件描述符
- 4. 使用 expect 工具
- 参考
问题
我有一个 Bash 脚本,它使用 read
命令以交互方式读取命令参数,例如 yes/no
选项。是否有一种方法可以在非交互式脚本中调用这个脚本,并将默认选项值作为参数传递?
我不止需要向交互式脚本传递一个选项。
回答
如果你的脚本是通过 read
命令在交互式环境下读取命令参数,并且你希望在非交互式脚本中传递参数,那么你可以使用以下几种方法来模拟交互式输入:
1. 使用 Here Document
Here Document 可以用来传递多行输入到脚本:
bash your-interactive-script.sh <<EOF
answer1
answer2
answer3
EOF
其中 answer1
, answer2
, 和 answer3
是对应于脚本中每一个 read
提示的输入。
2. 使用 echo 管道传递
可以通过 echo
命令和管道来传递输入值:
echo -e "answer1\nanswer2\nanswer3" | bash your-interactive-script.sh
在这里,-e
会启用对反斜杠转义的解释,\n
用于模仿输入键(ENTER)的效果。
3. 使用文件描述符
还可以使用文件描述符来模拟交互式输入:
exec 3< <(echo -e "answer1\nanswer2\nanswer3")
./your-interactive-script.sh <&3
exec 3<&-
在这里,打开了一个文件描述符 3
,并将其与提供输入的进程替换关联起来。你的脚本从该文件描述符中读取内容,而不是从标准输入(stdin)中读取。
最后使用命令 exec 3<&-
关闭这个文件描述符,这样可以防止资源泄露,并确保这个文件描述符可以在脚本或程序的后续部分重新使用。
在 Bash 脚本中,exec
命令用于执行命令并在当前 shell 环境中改变 shell 的行为。文件描述符是用于访问文件和流的小的、非负整数。常见的文件描述符包括 0
(标准输入 stdin)、1
(标准输出 stdout)和 2
(标准错误 stderr)。
下面是这条命令的一部分解释:
-
exec 3< ...
:这个命令会打开一个文件或者创建一个输入流,并将它分配给文件描述符3
。当你读取文件描述符3
时,你实际上会从这个文件或流中读取数据。 -
<&-
:这是用来关闭文件描述符的语法。具体到exec 3<&-
,这条命令会关闭之前分配给文件描述符3
的文件或流。
总的来说,exec 3< <(command)
会创建一个新的文件描述符 3
,并从 command
命令产生的输出中读取数据。当你完成使用这个文件描述符后,使用 exec 3<&-
就可以关闭这个文件描述符,这样可以防止资源泄露,并确保这个文件描述符可以在脚本或程序的后续部分重新使用。
测试截图:
4. 使用 expect 工具
对于需要等待特定提示或需要更多控制的复杂场景,可以使用 expect
工具:
#!/usr/bin/expect -f
spawn ./your-interactive-script.sh
expect "第一次提示"
send "answer1\r"
expect "第二次提示"
send "answer2\r"
expect "第三次提示"
send "answer3\r"
interact
你可以用以下命令来安装 expect
:
sudo apt-get install expect # Debian/Ubuntu 系统
或者
sudo yum install expect # CentOS/RHEL 系统
根据你的脚本输入场景的复杂程度来选择最合适的方法。如果只是一系列简单的输入,方法 1 和 2 可能是最简便的。但是,如果脚本需要更复杂的交互,expect
可能更合适。
#!/usr/bin/expect -f
spawn ./interactive-script.sh
expect "name"
send "Bob\r"
expect "age"
send "17\r"
interact
测试截图:
总之,根据你的脚本输入场景的复杂程度来选择最合适的方法。如果只是一系列简单的输入,方法 1 和 2 是最简便的。但是,如果脚本需要更复杂的交互,expect 更合适。
参考
- stackoverflow question 14392525
- Here-Documents
- man expect
相关阅读:
- sh和Bash的区别
- 2>&1是什么意思
- 如何使用bash脚本并行运行多个程序
- 为什么要使用xargs命令
- 在shell程序里如何从文件中获取第n行
- 如何用命令行将文本每两行合并为一行?