で、この質問の誰かが使用して問題を報告し、ここで文書を内部に引用された区切り文字の単語で$(...)
コマンド置換バックスラッシュ、\
文書トリガーの内部の行末の改行結ぶラインの継続が、ここでは同じながら、文書外予想通りコマンド置換の作品を。
簡単なドキュメントの例を次に示します。
cat <<'EOT'
abc ` def
ghi \
jkl
EOT
これには、行末に1つのバックティックと1つのバックスラッシュが含まれます。区切り文字は引用符で囲まれているため、本体内で展開は発生しません。すべてのBourne-alikesで、これはコンテンツを逐語的に出力します。次のようにコマンド置換内に同じドキュメントを配置した場合:
x=$(cat <<'EOT'
abc ` def
ghi \
jkl
EOT
)
echo "$x"
その後、それらは同じ動作をしなくなります。
dash
、ash
、zsh
、ksh93
、BusyBoxのはash
、mksh
、とSunOS 5.10 POSIXは、sh
以前のように、すべて、文書の逐語的な内容を与えます。- Bash 3.2では、一致しないバックティックに対して構文エラーが発生します。一致したバックティックを使用して、コマンドとしてコンテンツを実行しようとします。
- Bash 4.3は、「ghi」と「jkl」を1行にまとめますが、エラーはありません。
--posix
オプションでは、この影響を与えません。Kusalananda はpdksh
、同じように振る舞うと言っています(ありがとう!)。
元の質問で、これはBashのパーサーのバグだと言いました。それは...ですか?[更新:yes ] POSIXからの関連テキスト(すべてシェルコマンド言語定義から)は、次のとおりです。
- §2.6.3コマンドの置換:
$(command)形式では、開き括弧から対応する閉じ括弧までのすべての文字がコマンドを構成します。commandには、任意の有効なシェルスクリプトを使用できます。ただし、不特定の結果を生成するリダイレクトのみで構成されるスクリプトは除きます。
- §2.7.4ヒアドキュメント:
単語の一部が引用されている場合、区切り文字はwordの引用削除を実行して形成され、ヒアドキュメントの行は展開されません。
- §2.2.1エスケープ文字(バックスラッシュ):
<バックライン>の後に<改行>が続く場合、シェルはこれを行の継続と解釈します。<backslash>と<newline>は、入力をトークンに分割する前に削除されます。
- §2.3トークンの認識:
場合io_hereトークンが文法によって認識されている(シェル文法を、一つ以上のすぐ隣次以降の行の)改行が一つ以上のここで、ドキュメントの本体を形成トークンとの規則に従って解析されなければなりませんHere-ドキュメント。
io_hereを処理していない場合、シェルは、入力内の次の文字に以下の最初の適用可能なルールを適用することにより、入力をトークンに分割します。...
...
- 現在の文字が<バックスラッシュ>、一重引用符、または二重引用符であり、引用されていない場合、引用されたテキストの最後までの後続の文字の引用に影響します。引用のルールは、引用で説明されています。トークンの認識中、実際には置換は行われず、結果のトークンには、入力に含まれる文字(<newline>を除く)が含まれます。引用テキストの。
これについての私の解釈は$(
、終了するまでのすべての文字が)
逐語的にシェルスクリプトを構成するということです。ヒアドキュメントが表示されるため、ヒアドキュメントの処理は通常のトークン化の代わりに行われます。ヒアドキュメントには、引用符で囲まれた区切り文字があり、その内容は逐語的に処理されます。エスケープ文字が含まれることはありません。しかし、このケースは単に対処されておらず、両方の動作が許容されるという議論を見ることができます。関連するテキストをどこかでスキップした可能性もあります。
- この状況は他の場所でより明確になっていますか?
- (理論上)移植可能なスクリプトは何に依存できるはずですか?
- これらのシェル(Bash 3.2 / Bash 4.3 /その他すべて)の特定の処理は、規格で義務付けられていますか?禁止?許可?
echo "$x"
ですが、変数を検査するあらゆる方法が機能します。その行を下に編集しました。
$(...)
その出力に置き換えます...ここで、サブシェルでサンプルのコマンドを実行すると(bash
)、期待される結果が出力されます。「ghi」と「jkl」を折りたたむのは、コマンド置換に変換するときだけです。だから、これはバグ