web-dev-qa-db-ja.com

cat> file << "END"はどのように機能しますか?

$ cat > file << "END"
> asdf
> qwerty
> END
$ cat file
asdf
qwerty
$

上記のトリックがどのように機能するかわかりません。

cat > fileは私には多少理解できます。つまり、catの出力がリダイレクトされてfileに書き込まれているということです。

これはどのように<< "END"パートワーク?少なくとも、これは、文字列ENDcatへの入力として処理する必要があることを意味すると思います。つまり、どちらかと言えば、最後にfileを想定します。 ENDの3文字の1行のみを含める必要があります。これが「コンソールからの入力を受け入れ、ユーザーが区切り文字として扱う必要があるこの文字列を入力するまでcatにリダイレクトする」ことを意味する可能性は、私を超えています。

3
gaazkam

スクリプトファイルでの使用法を正しく説明しているため、問題はhere-documentsの動作ではないようです。彼らのインタラクティブな使い方を理解していないようです。以下は、(大いに簡略化された)クラッシュコースであり、うまくいけば問題が明確になります。

シェルは、一般的なすべてのUnixプロセスと同様に、データを読み書きするための入出力ストリームを備えています。少なくとも1つの入力ストリーム(stdinと呼ばれる)と2つの出力ストリーム(stdoutstderr)がありますが、読み取りのために必要な数だけ開閉できます。書き込み用(ほとんどの場合、ファイルからの読み取りまたはファイルへの書き込み用)。プロセスがストリームをどのように処理するかは、プロセスによって異なります。たとえば、catは、引数なしで呼び出されると、そのstdinstdoutにコピーします。シェルは通常、それらの入力ストリームを実行されるコマンドとして解釈します(そして、いくつかの構文に従ってそれらのコマンドの入力および出力ストリームをセットアップします)。

入力データはどこから来ますか?それらは、他のプロセスから送信されたり、ファイルから読み取られたり、ユーザーが直接入力したりすることができます。これは、シェルのstdinの最も一般的な状況です。この場合、ユーザー入力を受け取ってストリームにロードする別のプログラムが必要です。このようなプログラムはttyと呼ばれ、この場合、ストリームはttyに接続されていると言います(ttyはウィンドウを提供する端末エミュレーションプログラムですが、大まかに言えば、ストリームは端末に接続されています。)と言うこともできます。

シェルはstdinttyにアタッチされていることを認識し、動作が異なります。たとえば、入力を待機しているときにプロンプ​​トを出力しますが、実際には他の多くの違いはありません。プロンプトは通常user@Host:current_path$のようなものです。その正確な内容は、変数PS1を変更することで定義できます。通常の規則では、通常のユーザーの場合は$で終わり、rootの場合は#で終わります。

スクリプトを実行すると、シェルはそれを含むファイルに入力ストリームをアタッチし、そこからコマンドを読み取ります。コマンドの1つにhere-document、つまり<<ENDのようなものが含まれている場合、これは次のことを意味します。これ以降、このターミネーターのみを含む行まで、ストリームの解釈を停止しますコマンドとしてデータを取得し、それらを実行するコマンドのstdin(この場合はcat)に渡します。これは、おそらく別の見方ではありますが、すでに知っていることです。

入力がttyにアタッチされている場合、ヒアドキュメントは同じ意味です。ストリームデータをコマンドとして解釈するのを停止し、実行するコマンドのstdinに渡すことです。ターミネーターに。唯一の違いは、入力を待つときにプロンプ​​トを表示することです。このプロンプトは、シェルが入力データをコマンドとして解釈する場合に出力されるプロンプトとは異なり、それらが渡されることを通知します。変数PS2によって定義され、その値はデフォルトで>になります。 cat file > file << "END"を入力した後、ターミネーターが読み取られるまで、すべての行の先頭に表示されます。シェルが通常の動作を再開すると、そのPS1-プロンプトが出力され、入力がコマンドとして解釈されるのを待ちます。

9
Dario