[英]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
這會導致腳本並行執行兩項操作:
通過使用tee,文本將被寫入管道(java程序正在等待讀取)和文件。 -a選項將文本附加到文件而不是覆蓋它。
java程序還將其內容附加到out.txt(使用>>)。
然后我們將文件內容讀入OUTPUT變量並刪除該文件。
這不是一個完整的解決方案,因為......
......所以這是我現在所擁有的最好的。 當然,仍然會邀請更好的解決方案。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.