POSIXシェル注釈と行の連続

POSIXシェル注釈と行の連続

私の質問を明確にするために編集してください。

POSIXは次のように言います。

<newline>が<backslash>の後にある場合(引用符を除く)、シェルはそれを行の連続として解釈します。入力をトークンに分割する前に、<backslash>と<newline>を削除する必要があります。

しかし、dash他の実装では、入力に最初にラベルが付けられます。\<newline>その結果、認識されず# this is a comment \廃棄されます。この動作はPOSIXに準拠していますか? POSIXは再び言いますトークン化の前に連続した行を削除する必要があります。

次の手順は実際にPOSIXと互換性がありませんか?

  1. 完全な入力を読んでください。"echo hello ... \<newline> ... bye"
  2. 引用符のないコンテンツを検索して\<newline>削除します。"echo hello ... bye"
  3. トークン化:"echo"(discard ' ')"hello"(discard ' ')(discard "# ... bye")

Ubuntuでdash-0.5.10.2-6 sh(ダッシュ)を使用すると、次のようになります。

$ cat /var/tmp/test.sh
echo hello # this is a comment \
echo bye

$ sh /var/tmp/test.sh
hello
bye

#以降のすべての内容はコメントとして処理され、\以前のすべての内容は削除されるため、\ <newline>の行の連続は効果がないためです。

しかし、POSIX「エスケープ文字(バックスラッシュ)」セクション状態

入力をトークンに分割する前に、<backslash>と<newline>を削除する必要があります。

~から#コメントはトークン化で行われます。

echo hello # this is a comment \
echo bye

次のようにする必要があります。

echo hello # this is a comment echo bye

これはshがPOSIXと互換性がないことを意味しますか?それとも、この場合、コメントが行連続より優先される理由はありますか?

答え1

セクション1で説明されているように、シェルへの入力は文字ごとにスキャンされ、トークンに分割されます。トークン認識

[...] シェルは、以下の最初の適用可能な規則を適用して、入力をトークンに分割します。次の文字で入力に。

引用符はトークン認識プロセスの一部として扱われますが、質問の例を考慮すると、シェルは#その前に引用符で囲まれた改行文字に会います。

シェルが入力行をスキャンしている間に引用符なしのコメント文字に達すると、行の残りの部分(最後のバックスラッシュを含む)がコメントとして削除されます。

現在の文字がある場合、#その文字とすべての後続の文字(次の文字を除く)は<newline>コメントとして削除されます。行の終わりは<newline>コメントの一部とは見なされません。


引用した標準セクションは、引用するセクションでは、バックスラッシュの前に改行文字が表示されます。

引用符なしのAは、<backslash>a以外の後続の文字のリテラル値を保持する必要があります<newline>。が<newline>後に来ると、<backslash>シェルはそれを行の連続として解釈します。入力をトークンに<backslash>分割する前に削除する必要があります。<newline>[...]

これは、スキャナが実際に引用符なしのバックスラッシュを検出するまでは適用されません(トークン認識プロセスによって処理されます)。

現在の文字が<backslash>一重引用符または二重引用符であり、引用符が付けられていない場合は、引用符付きテキストが終了するまで後続の文字の引用符に影響します。引用規則は、「引用」で説明されているとおりです。

この回答ですでに述べたように、スキャナはコメント文字に最初に会い、バックスラッシュに会い、行の残りの部分(引用符を含む)をコメントとして扱うトークン認識ルールをトリガーします。したがって、行末改行への参照は決して適用されません。

答え2

興味深いアイデアです。バックスラッシュエスケープは、トークンが認識される前に入力全体に適用されるステップだと思うようですが、そうではありません。

入力は依然として左から右に厳密に評価され、引用などの他の場合に必要です。

echo 'foo\
bar'

別の状況は、状況上の理由により参照された規則が適用されない場合です。この場合、コンテキストはあなたのコメントに基づく引用符付き文字列です。

現在の文字が「#」の場合、その文字とそれ以降のすべての文字(次の文字を除く)はコメントとして削除されます。

文を引用する理由は、次のようにできるからです。

ec\
ho foo

そのため、左から右に表示して表示します。それでも一般的な状況では、トークンを分割する前にバックスラッシュ+改行文字を削除すると評価が簡単になりますecho

dashこの動作はPOSIXシェルにのみ適用されません。

答え3

答えてくれてありがとう。

\トークン化時に参照されたかどうかがわかっているため、\<newline>トークン化前に参照されていないコンテンツを削除することはできません。

入力をトークンに分割する前に、<backslash>と<newline>を削除する必要があります。

このステートメントは、単に他の参照とは異なり、すぐに\<newline>破棄されることを意味します。私はそう考えなければならない。

関連情報