web-dev-qa-db-ja.com

EOFを使用せずにbashスクリプトからのテキスト入力を自動化する

Ubuntu Linuxを実行しています。 myprogramというプログラムがあるとします。このプログラムは、ユーザーに入力を求めます。具体的には、ユーザーはプロンプトが表示されたら整数を入力して、 Enter。 bashスクリプトを使用してこのプロセスを自動化したいと思います。特に、myprogramを、たとえば100回実行したいと思います(1から100へのカウンターiを使用)。 myprogramを実行するたびに、プロンプトが表示されたらiの現在の値を入力します。

(ちなみに、myprogramはオプション/スイッチ-optionsを受け取ります。これらはすべて定数であり、bashスクリプト内で指定されます。)

このbashスクリプトの不完全なスケルトンは次のようになります。

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

次に、上記のコードを変更して、プログラムから要求されたときにiの現在の値が入力されるようにします。これを行う最良の方法は何ですか?

私が使用しているソフトウェアのWebサイトが示唆しています<<EOF行の終わりにmyprogram -optionsを使用しています。これは、入力が使用するために「ファイルの終わり」を調べるようにbashに指示すると思います。しかし、入力をファイルのendに配置したくない場合はどうなりますか? <<または<の直後に配置したい場合はどうなりますか?

その理由は、物事がより複雑になるからです。たとえば、整数カウンタjを導入すると、非線形で非順次的な方法で変化します。次に、各反復でjの現在の値をmyprogramに供給したいと思いますが、jの値は、myprogram -optionsの呼び出しとファイルの終わりEOF

何か提案はありますか?

10
Andrew

ほとんどすべてのプログラムで、echo $i | myprogram -optionsmyprogram -options <<<$iの両方が機能するはずです。これには、標準入力を介してプログラム$iに入力することで機能します。

<fooは、fooという名前のファイルの内容をstdinとして使用します。

<<fooは、それとfooのみで構成される行の間のテキストを標準入力として使用します。 Gillesが言ったように、これはhereドキュメント(heredoc)です。 EOFは実際にはファイルの終わりを意味するのではなく、単なる一般的なヒアドキュメントの区切り文字です(この例では、代わりに「foo」を使用しています)。

<<<fooは、文字列 "foo"を標準入力として使用します。変数$fooを指定することもできます。上で示したように、シェルはその内容をstdinとして使用します。ヒアドキュメントのようにブロック全体とは対照的に短い文字列を使用するため、これはherestringと呼ばれます。ヒア文字列はbashでは機能しますが、/bin/shでは機能しません。

14
Kevin

このWebサイトが推奨する構文は hereドキュメント と呼ばれます。ファイルプログラムへの入力は、<<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

上記のKevinとGillesの両方が言及しているドキュメント、または単純な配管が多くの場合機能します。

より複雑な状況では、Expectまたは同様のものを検討することをお勧めします(たとえば、Expect :: Simple CPANモジュールは、Perlの実装を使用するのが非常に簡単です)。個人的には、Perlモジュール(Expect自体はtcl)を好みますが、多くの一般的なスクリプト言語の実装があります。 whileとreadを使用して、アイデアのveryプリミティブ実装をshまたはbashで作成することも可能です。

Expectおよび同様のツールの一般的なアイデアは、プログラムの出力で指定された文字列またはパターンを待ってから、必要な入力を提供することです。

一般的な使用例は、文字列「ogin:」を「期待」する(つまり待機する)ことでログインを自動化し、ログイン名を送信してから、文字列「Word:」を期待してパスワードを送信することです。

Myprogramのソースがある場合、最後のオプションの1つは、変更したいコマンドをコマンドラインオプションとして受け取ることです。これは前もって少し作業量が増えるかもしれませんが、Expectをいじったり、そのように使用するように設計されていないプログラムにデータをパイプしたりするよりも、ずっと悪化しません。

...そして、アップストリームにmyprogramにパッチを送信することを忘れないでください:)彼らがあなたがそれをコーディングした方法が気に入らなくても、機能を自分で追加するのに十分なアイデアを好むかもしれません。上流の開発者は、要求や不満を言うよりも、お尻を降りて貢献する人々を高く評価する傾向があります。

3
cas