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


10

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

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

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

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

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

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

その理由は、物事がより複雑になるからです。たとえばj、いくつかの非線形、非順次的な方法で変化する整数カウンターを紹介します。私は、その後の現在値送りたいと思うjmyprogram各反復上に、しかし、の値がjへの呼び出しの間で変更される可能性がありmyprogram -options、ファイルの末尾EOF

何か提案はありますか?


回答:


14

ほぼすべてのプログラムの場合、両方echo $i | myprogram -optionsmyprogram -options <<<$iプログラムを供給することによって、動作するはず$i標準入力経由。

<foofoostdin という名前のファイルの内容を使用します。

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

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


9

このWebサイトで推奨されている構文は、ヒアドキュメントと呼ばれます。ファイルプログラムへの入力は、を含む行のすぐ下から始まり<<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

つまり、このコンテキストでのEOF は、スクリプトファイルの実際の終わりではなく、ファイルの終わりマーカーを意味します。テキスト「EOF」は任意のテキストです。<<文字の直後に使用したテキストは、ヒア・ナウ文書の終わりを示します。私は通常、EOFを使用します。これは、目立つため、たとえば、シェルスクリプトをプログラムで生成する場合(かなり頻繁に実行する場合)は、herenowドキュメント内にある可能性が非常に低いためです。
CAS

太字のEOFは<underscore> <underscore> EOF <underscore> <underscore>
cas

このようなヒアドキュメントを使用して、私はしばしば終了マーカーをのようなはるかに意味のある(そして「ランダムに」一致する可能性が低い)ものに変更しましたEND_OF_WHATEVER_FUNCTION。時々、スペース/サイズを「保存」しようとすることは、実際に何が起こっているかについて曖昧さを引き起こすため、実際には努力の無駄です。
キラーミスト

sleepスクリプトから読み取ったコマンドの間にどうすればよいでしょうか。
boltup_im_coding

@ unexpected62私はあなたが何を求めているのか理解できません。あなたはおそらくこのサイトで新しい質問をする必要があります。十分なコンテキストを提供してください。
Gilles「SO-邪悪なことをやめなさい」

3

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

より複雑な状況では、Expectまたは同様のものを調べたい場合があります(たとえば、Expect :: Simple CPANモジュールは、非常に使いやすいperl実装です)。個人的には、perlモジュール(Expect自体はtcl)を好みますが、多くの一般的なスクリプト言語の実装があります。whileとreadを使用して、アイデアの非常に原始的な実装をshまたはbashで作成することもできます。

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

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

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

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.