単語分割とは何ですか?なぜシェルプログラミングで重要なのですか?


16

単語分割が果たす役割について混乱していzshます。C、Python、またはMATLABでプログラミングするときにこの概念に触れたことはありません。これが、単語分割がシェルプログラミングに固有のものであるように思える理由への興味を引き起こしました。

このサイトや他のサイトで単語分割について読んだことがありますが、この概念の明確な説明は見つかりませんでした。ウィキペディアには単語分割の定義がありますが、Unixシェルへの適用方法についての言及はないようです。

以下に私の混乱の例を示しzshます。

ではZシェルよくある質問、私は以下をお読みください。

3.1:なぜ私が期待することを$varどこでしvar="foo bar"ないのですか?

ほとんどのBourneシェル派生物では、などの複数ワード変数 var="foo bar" は、コマンドに渡されるか、for foo in $varループで使用されるときにワードに分割されます。デフォルトでは、zshにはそのような振る舞いはありません。変数はそのまま残ります。(これはバグではありません!以下を参照してください。)SH_WORD_SPLIT互換性を提供するオプションがあります。

ただし、Z Shell Manualでは、次を読みました。

SH_WORD_SPLIT (-y) <K> <S>

引用符で囲まれていないパラメーター展開でフィールド分割を実行します。このオプション 単語の分割とは関係がないことに注意してください。(パラメータ拡張を参照してください。)

なぜそれは単語の分割とSH_WORD_SPLIT関係ないと言うのですか?単語の分割は、これがすべて何であるかを正確に示していませんか?

回答:


21

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

files="foo bar qux"
myprogram $files

myprogramシェルが文字列$filesを単語に分割するため、3つの引数で呼び出されます。当時、ファイル名のスペースは禁止されているか、広く行われていないとみなされていました。

Kornシェルは、配列を導入しました:あなたは変数に文字列のリストを格納することができます。Kornシェルは当時確立されていたBourneシェルとの互換性を保っていたため、裸の変数展開では単語分割が継続され、配列の使用には構文上のオーバーヘッドが必要でした。上記のスニペットを書きます

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

Zshには最初から配列があり、その作成者は下位互換性を犠牲にして、より健全な言語設計を選択しました。zshでは(デフォルトの展開規則の下では)$var単語分割を行いません。単語のリストを変数に保存する場合、配列を使用することになります。単語の分割が本当に必要な場合は、と書くことができます$=var

files=(foo bar qux)
myprogram $files

最近では、多くのユーザーが動作することを期待しているため、また攻撃者がファイル名を制御している可能性のあるセキュリティに敏感なコンテキストで多くのスクリプトが実行されるため、ファイル名のスペースに対処する必要があります。そのため、自動単語分割はしばしば厄介です。したがって、"$foo"特定のユースケースで単語の分割が必要な理由を理解していない限り、常に二重引用符を使用する、つまり書き込みを行う一般的なアドバイスです。(裸の変数展開もグロビングを受けることに注意してください。)


ジルに感謝します、これは本当に役に立ちます!大まかに言って単語分割は、フォームの文字列をフォームの"word1 word2 word3"リスト/配列に変換すると言うのは正しい"word1" "word2" "word3"ですか?また、zshの特定の混乱の原因でOPを更新しました。
アメリオバスケスレイナ

1
@intrpc「単語分割」は、自然言語の単語ではなく$IFS文字で分割されます。したがって、「フィールド分割」の方が適切な名前です。しかし、シェル文学ではこの概念に「単語分割」がよく使用されます。zshのドキュメントでは、言葉が混乱しています。
ジル「SO-悪であるのをやめる」

1
rc変数と配列に関しては、zshよりも優れた設計については(plan9シェル、Unixにも移植されています)も参照してください。
ステファンシャゼル

3

単語の分割は、実際にはシェル固有ではありません。

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

シェル固有のことは、(C argc / argv、python sys.argv)と呼ばれるコマンドの引数リストを適切に作成する必要があることです。埋め込みスペース、空の引数、カスタム区切り文字などの引数の受け渡しも含まれます。多くのシェルはIFS変数を使用して、そこにある程度の柔軟性を持たせています。


3

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

考えてくださいprog a b c、あなたがどのように設定しようと3つの引数を渡しますIFS。これは単語分割です。

使用するとA="a b c"; prog $AIFSスペースが含まれる場合は3つの引数を渡し、それ以外の場合は1つの引数を渡します。これはフィールド分割です。

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


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