在不使用 EOF 的情況下自動從 bash 腳本輸入文本

在不使用 EOF 的情況下自動從 bash 腳本輸入文本

我正在運行 Ubuntu Linux。假設有一個程式叫做myprogram.程式提示使用者輸入;具體來說,用戶必須在出現提示時鍵入整數並按Enter。我想使用 bash 腳本自動執行此過程。特別是,我想執行100 次(使用從 到的myprogram計數器)。在每次執行 時,我想在出現提示時輸入當前值。 i1100myprogrami

(順便說一句,myprogram採用 options/switches -options,所有這些都將是常數,因此在 bash 腳本中指定。)

該 bash 腳本的不完整骨架可能是:

#!/bin/bash
for i in {1..100}
do
   myprogram -options
done

現在我想修改上面的程式碼,以便i在程式提示時輸入當前值。做這個的最好方式是什麼?

我正在使用的軟體的網站建議<<EOF在行尾使用myprogram -options。我認為這告訴 bash 查看“文件末尾”以供使用的輸入。但是如果我不想將輸入放在結尾文件的?如果我想將其立即放在<<or後面怎麼辦<

原因是事情會變得更複雜。例如,我可能會引入一個j以某種非線性、非順序方式變化的整數計數器。然後,我希望在每次迭代時提供jto的當前值,但在呼叫和檔案末尾之間myprogram, 的值可能會發生變化。 jmyprogram -optionsEOF

你有什麼建議嗎?

答案1

幾乎所有程序, 和 都echo $i | myprogram -options應該myprogram -options <<<$i工作,透過標準輸入提供程序$i

<foo將使用名為 stdin 的檔案的內容foo

<<foo將使用該文字與僅由 組成的行之間的文字foo作為標準輸入。這是一個這裡的文檔(heredoc),正如吉爾斯所說;EOF實際上並不意味著文件的結尾,它只是一個常見的定界符描述符(在本例中我們使用“foo”來代替)。

<<<foo將使用字串“foo”作為標準輸入。您也可以指定一個變量$foo,shell 會將其內容用作標準輸入,如我上面所示。這被稱為此處字串,因為它使用一個短字串,而不是整個區塊,就像在定界文件中一樣。 Herestrings 在 bash 中有效,但在/bin/sh.

答案2

該網站推薦的語法稱為這裡的文檔。檔案程式的輸入緊接在包含 的行下方開始<<EOF,並且不會在腳本末尾處終止,而是在包含確切文字的行處終止EOF(注意不要有多餘的空格)。順便說一句,您可以使用任何不包含任何 shell 特殊字元的結束標記:EOF不是關鍵字,它只是傳統的。

#!/bin/bash
for i in {1..100}
do
   myprogram -options <<EOF
$i
EOF
   for j in {1..42}; do
     myprogram2 <<EOF
$i
$j
EOF
   done
done

答案3

上面凱文和吉爾斯提到的文件或簡單的管道在許多情況下都可以使用。

對於更複雜的情況,您可能需要研究 Expect 或類似的模組(例如 Expect::Simple CPAN 模組是一個非常易於使用的 perl 實作)。就我個人而言,我更喜歡 perl 模組(Expect 本身是 tcl),但有許多常見腳本語言的實作。甚至可以寫一個非常使用 while 和 read 在 sh 或 bash 中原始實作該想法。

Expect 和類似工具的整體思路是等待程式輸出中的指定字串或模式,然後向其提供所需的任何輸入。

一個常見的範例用途是自動登錄,透過“期待”(即等待)字串“ogin:”,發送登入名,然後期待字串“word:”並發送密碼。

如果您有 myprogram 的原始程式碼,最後一個選擇是修改它以取得您想要作為命令列選項提供的輸入。這可能需要更多的前期工作,但比亂搞 Expect 或將資料傳輸到並非設計用於這種方式的程式中要簡單得多。

……並且不要忘記將您的補丁提交到上游的 myprogram :) 即使他們不喜歡您編碼的方式,他們也可能非常喜歡這個想法,可以自己添加該功能。上游開發者傾向於欣賞那些奮力拼搏、做出貢獻的人,而不是要求或抱怨的人。

相關內容