$ cat > file << "END"
> asdf
> qwerty
> END
$ cat file
asdf
qwerty
$
上記のトリックがどのように機能するかわかりません。
cat > file
は私には多少理解できます。つまり、cat
の出力がリダイレクトされてfile
に書き込まれているということです。
これはどのように<< "END"
パートワーク?少なくとも、これは、文字列END
をcat
への入力として処理する必要があることを意味すると思います。つまり、どちらかと言えば、最後にfile
を想定します。 END
の3文字の1行のみを含める必要があります。これが「コンソールからの入力を受け入れ、ユーザーが区切り文字として扱う必要があるこの文字列を入力するまでcat
にリダイレクトする」ことを意味する可能性は、私を超えています。
スクリプトファイルでの使用法を正しく説明しているため、問題はhere-documentsの動作ではないようです。彼らのインタラクティブな使い方を理解していないようです。以下は、(大いに簡略化された)クラッシュコースであり、うまくいけば問題が明確になります。
シェルは、一般的なすべてのUnixプロセスと同様に、データを読み書きするための入出力ストリームを備えています。少なくとも1つの入力ストリーム(stdin
と呼ばれる)と2つの出力ストリーム(stdout
とstderr
)がありますが、読み取りのために必要な数だけ開閉できます。書き込み用(ほとんどの場合、ファイルからの読み取りまたはファイルへの書き込み用)。プロセスがストリームをどのように処理するかは、プロセスによって異なります。たとえば、cat
は、引数なしで呼び出されると、そのstdin
をstdout
にコピーします。シェルは通常、それらの入力ストリームを実行されるコマンドとして解釈します(そして、いくつかの構文に従ってそれらのコマンドの入力および出力ストリームをセットアップします)。
入力データはどこから来ますか?それらは、他のプロセスから送信されたり、ファイルから読み取られたり、ユーザーが直接入力したりすることができます。これは、シェルのstdin
の最も一般的な状況です。この場合、ユーザー入力を受け取ってストリームにロードする別のプログラムが必要です。このようなプログラムはtty
と呼ばれ、この場合、ストリームはtty
に接続されていると言います(tty
はウィンドウを提供する端末エミュレーションプログラムですが、大まかに言えば、ストリームは端末に接続されています。)と言うこともできます。
シェルはstdin
がtty
にアタッチされていることを認識し、動作が異なります。たとえば、入力を待機しているときにプロンプトを出力しますが、実際には他の多くの違いはありません。プロンプトは通常user@Host:current_path$
のようなものです。その正確な内容は、変数PS1
を変更することで定義できます。通常の規則では、通常のユーザーの場合は$
で終わり、root
の場合は#
で終わります。
スクリプトを実行すると、シェルはそれを含むファイルに入力ストリームをアタッチし、そこからコマンドを読み取ります。コマンドの1つにhere-document、つまり<<END
のようなものが含まれている場合、これは次のことを意味します。これ以降、このターミネーターのみを含む行まで、ストリームの解釈を停止しますコマンドとしてデータを取得し、それらを実行するコマンドのstdin
(この場合はcat
)に渡します。これは、おそらく別の見方ではありますが、すでに知っていることです。
入力がtty
にアタッチされている場合、ヒアドキュメントは同じ意味です。ストリームデータをコマンドとして解釈するのを停止し、実行するコマンドのstdin
に渡すことです。ターミネーターに。唯一の違いは、入力を待つときにプロンプトを表示することです。このプロンプトは、シェルが入力データをコマンドとして解釈する場合に出力されるプロンプトとは異なり、それらが渡されることを通知します。変数PS2
によって定義され、その値はデフォルトで>
になります。 cat file > file << "END"
を入力した後、ターミネーターが読み取られるまで、すべての行の先頭に表示されます。シェルが通常の動作を再開すると、そのPS1
-プロンプトが出力され、入力がコマンドとして解釈されるのを待ちます。