用bash捕获交互式程序的输出和输入

jth*_*man 5 linux bash shell

我正在努力使bash中的交互式命令行Java程序自动化,以验证该程序为输入产生了正确的输出(基本上是bash中的穷人单元测试)。

例如,如果我有一个Java程序要求用户输入其全名,然后仅输出其名字,则它应如下所示:

Enter your name: John Doe
John
Run Code Online (Sandbox Code Playgroud)

用户输入“ John Doe”的位置。

运行此命令的简单bash命令如下所示:

OUTPUT=`echo "John Doe" | java NameReader`
Run Code Online (Sandbox Code Playgroud)

要么

OUTPUT=`java NameReader <<< "John Doe"`
Run Code Online (Sandbox Code Playgroud)

两者的麻烦在于$ OUTPUT现在包含以下内容:

Enter your name: John
Run Code Online (Sandbox Code Playgroud)

因为发送到stdin的文本(及其伴随的换行符)不会像我们在控制台中看到的那样在程序的输出中复制。

理想情况下,$ OUTPUT将包含以下内容:

Enter your name: John Doe
John
Run Code Online (Sandbox Code Playgroud)

但是我可以忍受这个:

Enter your name: 
John
Run Code Online (Sandbox Code Playgroud)

(输入被完全省略,但是输出如预期的那样在新行中)

bash中是否有一种方法(不更改底层的Java程序)来获取被输送到stdin的文本,也可以在Java程序读取的“时间”将其输送到stdout,因此捕获了完整的交互式会话?

(另一个注意事项:一些搜索表明spawn / expect命令可能会有所帮助,但是将在其上运行的系统似乎没有可用的命令)

Ada*_*dam 5

您可以使用以下script命令

script -q -c "java NameReader" log.txt
Run Code Online (Sandbox Code Playgroud)

这将java NameReaderlog.txt文件中记录命令的输入和输出。


Sim*_*lbc 1

如果你的java程序是这样的:

import java.util.Scanner;
class A {
        public static void main(String[] args) {
                Scanner sc = new Scanner(System.in);
                System.out.println(sc.next());
        }
}
Run Code Online (Sandbox Code Playgroud)

然后你可以构建一个 bash 脚本来解析表单的输入

Enter your name: John
John Doe
Run Code Online (Sandbox Code Playgroud)

将其转变为

Enter your name: John Doe
John
Run Code Online (Sandbox Code Playgroud)

这是一种可能的 bash 脚本:

#!/bin/bash
arg1Outpt=`eval "$1"`
javaOut=`echo "$arg1Outpt" | eval "$2"`
#prints Enter your name: John\nJohn Doe      
echo "${javaOut}"$'\n'"${arg1Outpt}" |
                        sed 'N; s/\(Enter your name: \)\(.*\)\(\n\)\(.*\)/\1\4\3\2/'
                        #and this is a multiline sed(man sed) that transforms your 
                        #input into what you want :)
Run Code Online (Sandbox Code Playgroud)

像这样使用它:

bash pipeCheat.bash 'echo "john doe"' 'java A'
Run Code Online (Sandbox Code Playgroud)

其中,pipeCheat.bash 是保存上述脚本的文件的名称。

如果您有疑问,请随时提问。