存在するHEREDOCテキストをシェルスクリプト変数にどのように入れますか?誰かが以下を使用して問題を報告します。ここのドキュメント内部に引用符の区切り記号があります。$(...)
コマンドの置き換え\
、ドキュメント行の末尾にあるバックスラッシュがトリガーされます。Newline - 行継続接続、ここにある文書は同じですが、外部コマンド置換が期待どおりに機能します。
以下は単純化されたサンプル文書です。
cat <<'EOT'
abc ` def
ghi \
jkl
EOT
これには、行の末尾にバックティックとバックスラッシュが含まれます。区切り文字が引用されているため、本文内で拡張は行われません。 Bourneのようなすべてのプログラムでは、そのまま出力されることがわかります。同じ文書を次のコマンド置換に入れると:
x=$(cat <<'EOT'
abc ` def
ghi \
jkl
EOT
)
echo "$x"
これはもはや同じように動作しません。
dash
、、、、、BusyBox、およびSunOS 5.10 POSIXは、ash
以前と同様にドキュメントの内容をそのまま提供します。zsh
ksh93
ash
mksh
sh
- Bash 3.2では、バックティックの不一致が原因で構文エラーが発生します。一致するバックティックを使用すると、コンテンツをコマンドとして実行しようとします。
- Bash 4.3では、「ghi」と「jkl」をエラーなしで1行に縮小します。これ
--posix
オプションこれには影響しません。先行は達成するのが難しいpdksh
同じように動作すると言ってください(ありがとうございます!)。
元の質問では、私はこれがBashパーサーのバグだと言いました。うん? [修正する:はい]私が見つけることができるPOSIXの関連テキスト(すべてShellコマンド言語定義で)は次のとおりです。
- §2.6.3コマンドの置き換え:
$(command)形式の場合、左角かっこの後から右角括弧までのすべての文字がコマンドを構成します。有効なシェルスクリプトは何でも使用できます。注文する、指定されていない結果を生成するリダイレクトのみで構成されたスクリプトは除外されます。
- §2.7.4 ここの文書:
どんな部分でも言葉引用符がある場合は、引用符を削除して区切り文字を形成する必要があります。言葉、ドキュメント行はここで拡張してはいけません。
- §2.2.1エスケープ文字(バックスラッシュ):
<newline>が<backslash>の後に来ると、シェルはそれを行の連続として解釈します。入力をトークンに分割する前に、<backslash>と<newline>を削除する必要があります。
- §2.3トークンの識別:
いつio_ここトークンは文法によって認識されました(参照:シェル構文)、次の行の直後に続く1つ以上の行新しいチームトークンはここで1つ以上の文書本文を形成し、次の規則に従って解析する必要があります。ここのドキュメント。
処理できないときio_ここ、シェルは、次の最初の適用可能な規則を入力の次の文字に適用して、入力をトークンに分割する必要があります。 ...
...
- 現在の文字が<バックスラッシュ>、一重引用符または二重引用符であり、引用符がない場合は、引用符付きテキストが終わるまで後続の文字の引用符に影響します。引用規則は次のとおりです。引用する。トークン認識中に置換は実際には行わないでください。結果トークンには、入力に現れる文字(<newline>接続を除く)を変更せずに正確に含める必要があります。引用符と末尾の間に挿入または囲まれた引用符または引用符付きテキストする必要があります。置換演算子。
これに対する私の解釈は、$(
終了までのすべての文字が)
文字通りシェルスクリプトを構成することです。したがって、文書処理は一般的なトークン化の代わりにここで行われ、これはその文書の内容が引用符で囲まれた区切り文字を持つことを意味します。そのまま処理され、エスケープ文字は決して表示されません。しかし、この状況はまったく解決されず、両方の行為が許されるという主張が見られます。どこかで関連テキストをスキップした可能性があります。
- この状況は他の場所でより明確に明らかになりましたか?
- 移植可能なスクリプトは(理論的には)何に依存できるべきですか?
- 標準では、これらのシェル(Bash 3.2 / Bash 4.3 /その他すべて)の特定の処理が必要ですか?禁止?許可されますか?
ベストアンサー1
これはBashメーリングリストで要求されており、管理者はこれがバグであることを確認しました。
また、POSIXのテキストは「必ずしも曖昧ではありませんが、注意深く読まなければならない」と言及し、これについての明確な説明を要請しました。彼らの答えには、問題の説明と基準の説明が含まれていました。次のように:
コマンドの置換は、間違った点を指摘するという点でのみ関連しています。
ここでは、ドキュメントの区切り文字が引用されているため、行は拡張されません。この場合、シェルは引用したように入力から行を読み取ります。バックスラッシュが引用符付きコンテキストに表示されると、エスケープ文字として機能せず(以下を参照)、バックスラッシュの改行に対する特別な処理は行われません。実際に区切り文字の一部が引用されている場合、ここのドキュメント行は一重引用符で読み取られます。
Posix 2.2.1のテキストは奇妙に書かれていますが、これはバックスラッシュが引用されていない場合にのみ特別に扱われることを意味します。バックスラッシュを引用して一重引用符を使用するか、他のバックスラッシュを使用してすべての拡張を抑制できます。
その部分は一重引用符を意味する「拡張されていない」テキストであることを注意深く読んでください。標準は2.2でこの文書は「引用の別の形式」と言いますが、単語がまったく拡張されない唯一の引用形式は一重引用符です。したがって、一重引用符とまったく同じですが、別の引用形式です。