噴射とは何ですか?シェルプログラミングでは、なぜこれが重要なのでしょうか?

噴射とは何ですか?シェルプログラミングでは、なぜこれが重要なのでしょうか?

で噴射の役割が混乱していますzsh。私はC、Python、またはMATLABでプログラミングしている間、この概念に触れたことがなかったので、単語分割がシェルプログラミングに固有のように見える理由に興味がありました。

以前はこのサイトとは異なるサイトで単語の分割について読みましたが、概念の明確な説明が見つかりませんでした。ウィキペディアには一つあります。噴射の定義しかし、これがUnixシェルにどのように適用されるかについての言及はないようです。

私の混乱の例は次のとおりですzsh

内部にZシェルのよくある質問、私は以下を読んだ。

3.1:なぜ私の期待に満たない$var場所がありますか?var="foo bar"

ほとんどのBourne-shell派生項目では、マルチワード変数(たとえば)は、 var="foo bar" コマンドに渡されるかループで使用されるときに単語に分割されますfor foo in $var。デフォルトでは、zshにはこれらの動作はありません。変数は変更されていません。 (これはエラーではありません!以下を参照してください。)このオプションはSH_WORD_SPLIT互換性のために存在します。

しかし、Z Shell マニュアルで、私は以下を読んだ。

SH_WORD_SPLIT (-y) <K> <S>

引用符なしのパラメータ拡張では、フィールド分割が実行されます。このオプションに注意してください何もしない 噴射で。 (パラメータの拡張を参照してください。)

SH_WORD_SPLITなぜあるというの?何もしない噴射で?これは噴射ではありませんか?

答え1

初期シェルには、文字列という単一のデータ型しかありませんでした。しかし、通常、複数のファイル名をプログラムに引数として渡すときに文字列リストを操作するのは非常に一般的です。分割のもう一つの一般的なユースケースは、コマンドが結果リストを出力する場合です。コマンドの出力は文字列ですが、必要なデータは文字列のリストです。変数にファイル名のリストを保存するには、名前の間にスペースを追加します。その後、このようなシェルスクリプト

files="foo bar qux"
myprogram $files

myprogramシェルが文字列を単語に分割すると、$files3つの引数で呼び出されます。当時、ファイル名の空白は禁止されているか、未完成と広く考えられていました。

これコーエンシェル配列の紹介:文字列のリストを変数に保存できます。 Kornシェルは当時確立されたBourneシェルとまだ互換性があるため、デフォルトの変数拡張は継続的なトークン化を実行し、配列を使用するにはわずかな構文オーバーヘッドが必要です。上記のスニペットを作成できます。

files=(foo bar qux)
myprogram "${files[@]}"

Zshは最初から配列を持っており、作者は以前のバージョンとの互換性を犠牲にしてより合理的な言語デザインを選択しました。 zshでは(デフォルトの拡張規則に従って)$var単語の分離は行われません。単語リストを変数に保存するには、配列を使用する必要があります$=var

files=(foo bar qux)
myprogram $files

ファイル名の空白は、最近扱うべき問題です。これは、多くのユーザーが空白が機能することを期待し、攻撃者が潜在的にファイル名を制御できるセキュリティに敏感なコンテキストで多くのスクリプトが実行されるためです。したがって、単語の自動分離はしばしば問題になります。したがって、一般的なアドバイスは、"$foo"特定のユースケースで単語の分離が必要な理由を理解していない限り、常に二重引用符を使用することです。 (基本変数の拡張にもワイルドカードが発生することに注意してください。)

私の答えでは、私は「スプレー」という言葉を使いました。変数を設定して単語(フィールドとも呼ばれる)の構成を構成できるため、これを「フィールド分割」ともいいますIFS。単語内のすべての文字はIFS単語区切り文字と見なされ、単語は単語ではなく一連の文字です。分離記号。IFSデフォルトでは、デフォルトの空白文字が含まれます(キャリッジリターン、分割できないスペースなどではなく、ASCIIスペース、タブ、および改行)。zshマニュアルでは、「単語の分離」はシェルコードの解析手順を参照するためにのみ使用され、変数とコマンドの置換後に発生する拡張の一部であるフィールド/単語の分割とは関係ありません。

答え2

Zshの特定のケースでは、単語分割はフィールド分割とは少し異なるように定義されます。

考えてみてくださいprog a b c。どのように設定しても、3つのパラメータを渡しますIFS。これは言葉分けた。

これが完了すると、スペースが含まれている場合は3つの引数を渡し、そうでない場合は1つの引数を渡しますA="a b c"; prog $AIFSこれは大地分けた。

ここでの定義は微妙です。 Zshドキュメントで言うことは、オプションを無効にしてもprog a b cまだ別の引数を取得することです(これは常に期待されるものです)。

答え3

トークン化は実際にはシェルに限定されない。

テキスト入力を解析する必要があるほとんどのプログラムは、最初のステップとして一種のトークン化を使用します。これは、数値、演算子、文字列、トークン、およびこれらの「単語」で処理する必要がある類似のエンティティを識別する前に行われます。

シェルは、空白を含む引数渡し、空の引数、カスタム区切り文字などを含むコマンド(C argc / argv、python sys.argv)の引数リストを正しく設定する必要があるという点で具体的です。多くのシェルは柔軟性を提供するためにIFS変数を使用します。

関連情報