如何让Bash脚本向控制台程序传输入时显示输入并保持交互格式
问题:bash脚本传递输入时匹配交互式程序的输出格式
我的控制台程序在Ubuntu 20.04下运行,交互式模式下输入表达式(比如a+b)时,输入会显示在提示符旁,换行后输出结果,格式如下:
$ ./rec_desc1 Enter expression: a+b F --> id R --> eps T --> FR F --> id R --> eps T --> FR Q --> eps Q --> +TQ E --> TQ Success.
但用bash脚本的here-string或管道传递输入时,输入不会显示,而且第一行输出会直接贴在提示符后面,示例如下:
脚本rec_desc1_unit_test内容:
#!/bin/bash echo "Test case 1" ./rec_desc1 <<< a+b
运行脚本的输出:
$ ./rec_desc1_unit_test Test case 1 Enter expression: F --> id R --> eps T --> FR F --> id R --> eps T --> FR Q --> eps Q --> +TQ E --> TQ Success.
我需要通过bash脚本运行大量测试用例,希望传递输入时能让输入显示在提示符旁并换行,和交互式格式完全一致,实现测试的自文档化。试过在调用程序前用set -v,但之后必须立即用set +v避免显示后续的echo语句,不想每个测试用例都套一遍这个。
解决方案
方法1:用script模拟交互式终端
script命令可以创建伪终端环境,让程序误以为是在交互式模式下运行,自动回显输入内容,完美匹配交互式输出格式。
修改脚本如下:
#!/bin/bash echo "Test case 1" script -q /dev/null -c "./rec_desc1 <<< a+b"
参数说明:
-q:静默模式,不显示script自身的启动/结束提示/dev/null:不保存会话日志(如果需要记录日志可以换成文件路径)-c:指定要运行的命令
运行后输出和交互式完全一致:
Test case 1 Enter expression: a+b F --> id R --> eps T --> FR F --> id R --> eps T --> FR Q --> eps Q --> +TQ E --> TQ Success.
方法2:封装函数批量处理测试用例
如果有大量测试用例,可以把测试逻辑封装成函数,避免重复代码:
#!/bin/bash # 定义测试函数:参数1为测试名称,参数2为表达式 run_test() { local test_name="$1" local expr="$2" echo "$test_name" script -q /dev/null -c "./rec_desc1 <<< '$expr'" echo "" # 用空行分隔不同测试用例 } # 批量执行测试 run_test "Test case 1: 加法表达式a+b" "a+b" run_test "Test case 2: 混合表达式c*d-e" "c*d-e" run_test "Test case 3: 单个标识符f" "f"
这样每个测试用例只需调用函数,无需重复编写script的复杂参数,输出格式统一且清晰。
方法3:修改程序本身(若有权限)
如果可以修改控制台程序的代码,直接在程序内部处理格式统一问题。通过isatty()函数判断是否为交互式终端,非交互式时主动打印输入内容:
以C语言为例:
#include <stdio.h> #include <unistd.h> #include <string.h> int main() { char expr[1024]; printf("Enter expression: "); fflush(stdout); // 确保提示符立即输出,避免缓冲 if (fgets(expr, sizeof(expr), stdin) != NULL) { // 去掉换行符 expr[strcspn(expr, "\n")] = '\0'; // 非交互式终端时,主动打印输入内容 if (!isatty(fileno(stdin))) { printf("%s\n", expr); } // 以下是原有的解析逻辑... printf("F --> id\n"); printf("R --> eps\n"); printf("T --> FR\n"); printf("F --> id\n"); printf("R --> eps\n"); printf("T --> FR\n"); printf("Q --> eps\n"); printf("Q --> +TQ\n"); printf("E --> TQ\n"); printf("Success.\n"); } return 0; }
修改后,无论用交互式还是脚本传递输入,输出格式都会完全一致,无需脚本额外处理。
内容的提问来源于stack exchange,提问作者Mr. D.
相关产品推荐
相关产品推荐

