使用bash

时间:2016-05-18 17:02:56

标签: linux bash shell

我正在使用bash自动化交互式命令行Java程序来验证程序是否为输入生成了正确的输出(基本上是穷人在bash中进行单元测试)。

例如,如果我有一个java程序要求用户输入他们的全名,然后只输出他们的名字,它应该是这样的:

Enter your name: John Doe
John

John" John Doe"是由用户输入的。

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

OUTPUT=`echo "John Doe" | java NameReader`

OUTPUT=`java NameReader <<< "John Doe"`

这两个问题都是$ OUTPUT现在包含以下内容:

Enter your name: John

因为发送到stdin的文本(及其附带的换行符)不会在程序输出中以我们在控制台中看到的方式再现。

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

Enter your name: John Doe
John

但我可以忍受这个:

Enter your name: 
John

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

在bash中是否存在一种方法(不改变底层的java程序)以获取正在通过管道传输到stdin的文本,以便在&#34; time&#34;它是由java程序读取的,因此捕获完整的交互式会话?

(还有一点需要注意:有些搜索表明spawn / expect命令可能会有所帮助,但是这个运行的系统似乎没有它们可用)

3 个答案:

答案 0 :(得分:3)

您可以使用java NameReader命令

log.txt

这将记录Session("CatMessage") = "Completed" Dim label As System.Web.UI.WebControls.Literal label = DirectCast(UserControl.FindControl("lblCatQuestion"), System.Web.UI.WebControls.Literal).Text = Session("CatMessage") 文件中"image/x-portable-bitmap" 命令的输入和输出。

答案 1 :(得分:1)

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

{
  "errorMessage": "class com.fasterxml.jackson.module.scala.ser.ScalaIteratorSerializer overrides final method withResolved.(Lcom/fasterxml/jackson/databind/BeanProperty;Lcom/fasterxml/jackson/databind/jsontype/TypeSerializer;Lcom/fasterxml/jackson/databind/JsonSerializer;)Lcom/fasterxml/jackson/databind/ser/std/AsArraySerializerBase;",
  "errorType": "java.lang.VerifyError"
}

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

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

将其转换为

Enter your name: John
John Doe

这是一个可能的bash脚本:

Enter your name: John Doe
John

像这样使用它:

#!/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 :)

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

如果您有任何疑问,请不要犹豫。

答案 2 :(得分:0)

这就是我最终做的事情。它不是一个完整的解决方案,但它适用于这种情况,对于后来遇到类似事情的其他人可能会有用:

{ sleep 3; echo "John Doe" | tee -a out.txt; } | java  NameReader >> out.txt
OUTPUT=`cat out.txt`
rm out.txt

这会导致脚本并行执行两项操作:

  1. 等待3秒钟,然后将文本“John Doe”写入管道和文件out.txt
  2. 运行java程序。
  3. 通过使用tee,文本将被写入管道(java程序正在等待读取)和文件。 -a选项将文本附加到文件而不是覆盖它。

    java程序还将其内容附加到out.txt(使用&gt;&gt;)。

    然后我们将文件内容读入OUTPUT变量并删除文件。

    这不是一个完整的解决方案,因为......

    1. 只要java程序正在运行并且在3秒睡眠期间等待用户输入,它就可以正常工作。如果不是,那么输出将是乱码。虽然期望程序在3秒后等待输入是合理的(在这种情况下),但肯定无法保证。
    2. 3秒延迟使得过程慢于必要。如果java程序在1秒之后就可以输入了,那么我们将花费2秒钟无所事事。如果要多次运行,可能会增加。
    3. 它仅适用于采用单一输入的交互式程序。有可能使用具有不同睡眠长度的多个“睡眠/回声/ T形”构造来响应多行,但这似乎会很快变得复杂和缓慢。
    4. ...所以这是我现在最好的。当然,仍然会邀请更好的解决方案。