Ubuntu Linux を実行しています。 というプログラムがあるとしますmyprogram
。このプログラムはユーザーに入力を求めます。具体的には、プロンプトが表示されたらユーザーは整数を入力して を押す必要がありますEnter。このプロセスを bash スクリプトを使用して自動化したいと思います。具体的には、 をたとえば 100 回実行したいと思います(からまでのmyprogram
カウンターを使用)。 を実行するたびに、プロンプトが表示されたら の現在の値を入力したいと思います。 i
1
100
myprogram
i
(ちなみに、myprogram
オプション/スイッチを取りますが-options
、これらはすべて定数なので、bash スクリプト内で指定されます。)
この bash スクリプトの不完全なスケルトンは次のようになります。
#!/bin/bash
for i in {1..100}
do
myprogram -options
done
i
ここで、上記のコードを変更して、プログラムからプロンプトが表示されたときに の現在の値が入力されるようにしたいと思います。これを行う最善の方法は何でしょうか?
私が使用しているソフトウェアのウェブサイトでは、<<EOF
行末にusing を使用しますmyprogram -options
。これは、bash に入力として「ファイルの末尾」を参照するように指示していると思います。しかし、入力を行末に置きたくない場合はどうすればよいのでしょうか。終わり<<
ファイルのまたはの直後に置きたい場合はどうすればいいでしょうか<
?
その理由は、物事がより複雑になるからです。たとえば、j
非線形かつ非連続的に変化する整数カウンタを導入するとします。その場合、各反復で の現在の値をj
に入力する必要がありますmyprogram
が、 の値はj
の呼び出しmyprogram -options
とファイルの終わりの間で変わる可能性がありますEOF
。
何か提案はありますか?
答え1
ほとんどすべてのプログラムでは、標準入力を介してプログラムを入力することにより、echo $i | myprogram -options
と の両方が機能するはずです。myprogram -options <<<$i
$i
<foo
stdin という名前のファイルの内容を使用しますfoo
。
<<foo
は、その行と、その行のみで構成される行の間のテキストをfoo
標準入力として使用します。これはここに文書(ヒアドキュメント) は、Gilles が言ったように、EOF
実際にはファイルの終わりを意味するわけではなく、一般的なヒアドキュメントの区切り文字にすぎません (この例では代わりに "foo" を使用します)。
<<<foo
文字列「foo」を標準入力として使用します。変数を指定することもできます。$foo
その場合、シェルはその内容を上記で示したように標準入力として使用します。これはヒアストリングは、heredoc のようなブロック全体ではなく、短い文字列を使用するためです。herestrings は bash では機能しますが、 では機能しません/bin/sh
。
答え2
このウェブサイトで推奨されている構文は、ここに文書ファイル プログラムへの入力は、 を含む行のすぐ下から始まり<<EOF
、スクリプトの終わりではなく、テキストとまったく同じ内容の行で終了しますEOF
(余分な空白がないように注意してください)。 ちなみに、シェルの特殊文字を含まない任意の終了マーカーを使用できます。 は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
ここで、上記の Kevin と Gilles の両方が言及しているようにドキュメントを作成するか、単純なパイピングで多くの場合は機能します。
もっと複雑な状況では、Expect や類似のものを検討した方が良いかもしれません (例えば、Expect::Simple CPAN モジュールは、非常に使いやすい Perl 実装です)。個人的には、Perl モジュール (Expect 自体は Tcl) を好みますが、多くの一般的なスクリプト言語用の実装があります。とてもwhile と read を使用して、sh または bash でこのアイデアを原始的に実装します。
Expect や同様のツールの基本的な考え方は、プログラムの出力で指定された文字列またはパターンを待機し、必要な入力を入力することです。
一般的な使用例としては、文字列「ogin:」を「期待」(つまり待機)してログイン名を送信し、次に文字列「word:」を期待してパスワードを送信することで、ログインを自動化することが挙げられます。
最後のオプションは、myprogram のソースがある場合、それを変更して、コマンドライン オプションとして渡したい入力を受け取るようにすることです。これは、事前に少し手間がかかるかもしれませんが、Expect をいじったり、そのように使用するために設計されていないプログラムにデータをパイプしたりするよりも、はるかに手間がかかりません。
... そして、アップストリームの myprogram にパッチを送信することを忘れないでください :) たとえコーディング方法が気に入らなくても、アイデアが気に入って自分で機能を追加するかもしれません。アップストリームの開発者は、要求したり文句を言ったりするよりも、やる気を出して貢献してくれる人を評価する傾向があります。