簡體   English   中英

使用bash捕獲交互式程序的輸出和輸入

[英]Capturing output and input of interactive program with bash

我正在使用bash自動化交互式命令行Java程序來驗證程序是否為輸入生成了正確的輸出(基本上是窮人在bash中的單元測試)。

例如,如果我有一個java程序要求用戶輸入他們的全名,然后只輸出他們的名字,它應該是這樣的:

Enter your name: John Doe
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的文本,以便在java程序讀取的“時間”內輸出到stdout,從而捕獲完整的交互式會話?

(還有一點注意:有些搜索表明spawn / expect命令可能會有所幫助,但是這個運行的系統似乎沒有它們可用)

您可以使用script命令

script -q -c "java NameReader" log.txt

這將在log.txt文件中記錄java NameReader命令的輸入和輸出。

如果你的java程序是這樣的:

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

然后你可以構建一個解析表單輸入的bash腳本

Enter your name: John
John Doe

將其轉化為

Enter your name: John Doe
John

這是一個可能的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 :)

像這樣用它:

bash pipeCheat.bash 'echo "john doe"' 'java A'

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

如果您有疑問,請不要猶豫。

這就是我最終做的事情。 它不是一個完整的解決方案,但它可以在這種情況下工作,對於后來遇到類似事情的其他人可能會有用:

{ 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程序。

通過使用tee,文本將被寫入管道(java程序正在等待讀取)和文件。 -a選項將文本附加到文件而不是覆蓋它。

java程序還將其內容附加到out.txt(使用>>)。

然后我們將文件內容讀入OUTPUT變量並刪除該文件。

這不是一個完整的解決方案,因為......

  1. 只要java程序正在運行並在3秒睡眠期間等待用戶輸入,它就可以工作。 如果不是,那么輸出將是亂碼。 雖然合理(在這種情況下)期望程序在3秒后等待輸入是合理的,但肯定不能保證。
  2. 3秒的延遲使得該過程比必要的慢。 如果java程序在1秒之后就可以輸入了,那么我們將花費2秒鍾無所事事。 如果要多次運行,可能會增加。
  3. 它只適用於采用單一輸入的交互式程序。 有可能使用具有不同睡眠長度的多個“睡眠/回聲/ T形”構造來響應多行,但這似乎會很快變得復雜和緩慢。

......所以這是我現在所擁有的最好的。 當然,仍然會邀請更好的解決方案。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM