POSIXスクリプトで二重引用符を印刷するには?

POSIXスクリプトで二重引用符を印刷するには?

これまで、私は次のように"\""二重引用符を印刷してきました。

$ x="abc def"
$ echo "x=\"$x\""
x="abc def"

しかし、この動作は定義されていないようですか?

~のためecho https://pubs.opengroup.org/onlinepubs/9699919799/utilities/echo.html(XSI互換システムの追加仕様を無視すると)バックスラッシュは完全に未定義の動作につながります。

標準出力に書き込まれる文字列。最初のオペランドが-nの場合、またはオペランドに<backslash>文字が含まれている場合、結果は実装に従って定義されます。

このページはprintf https://pubs.opengroup.org/onlinepubs/9699919799/utilities/printf.html主にファイル形式記号を表します。https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap05.html#tag_05これもサポートされていません\"

次の2つの方法はどうですか?明示的にPOSIXに準拠していますか?

  • 接続'"文字列

    $ x="abc def"
    $ printf x=%s\\n '"'"$x"'"'
    x="abc def"
    
  • 8進値の使用"

    $ x="abc def"
    $ printf x=\\42%s\\42\\n "$x"
    x="abc def"
    

代替は何ですか?

ベストアンサー1

はい、この動作(使用法\")はPOSIXのechoどこにでもコマンドに対して定義されていません。これがechoの代わりにprintfを使用する理由の1つです。読んでくださいなぜprintfがechoより優れているのですか?

もちろん、ここではいくつかの説明が必要です。

A\"実装定義それだけの場合オペランドエコ。

ここで言葉の定義はどれほど重要ですか?コマンドラインに書き込む内容は何度も読んで修正してからユーティリティにオペランドとして提供。私たちがコマンドライン引数(「単語」)と呼ぶことは、シェルによってさまざまな方法に変換されます。最後の変更の1つは「引用符の削除」です。結局これが結果だったらオペランドContainsは、\"echo正しい」と見なされるすべてのタスクを実行する権利があります。

コマンドラインがオペランドとecho '\"'ORecho "\\\""で連結されている場合、\"結果は実装に従って定義されます。

あなたの例x="abc def"; echo "x=\"$x\""は次のとおりですいいえ実装によって定義されます。 echoによって受信されたオペランドはですx="abc def"。しかし、変数の内容によって異なりますx

そのようなことを防ぐために可能質問オペランドが何であれ、出力はPOSIXとして定義されているため、無制限のprintfを使用する必要があります。

したがって、二重引用符を印刷する一般的な解決策は、printfコマンドのフォーマット部分にそれを置くことです。

$ printf 'x="%s"\n' "$x"
x="abc def"

一重引用符を印刷する必要がある場合は、引用符を変更するか、「引用符の終了 - 一重引用符を入れる - 引用符を再開」という一般的なトリックを使用する必要があります。

$ printf 'x='\''%s'\''\n' "$x"
x='abc def'

または:

$ printf "x='%s'"'\n' "$x"
x='abc def'

あるいは、より良い方法は、単一引用符を二重引用符で囲まれた文字列に切り替えることです。

$ printf 'x=%s\n' "'$x'"
x='abc def'

\dddしかし、そうです。 printf は 8 進数をサポートしているので、次のものを使用することdddもできます。

$ printf 'x=\042%s\042\n' "$x"
x="abc def"

上記のソリューションはすべて有効なPOSIX構成です。 1つを選択してください。

おすすめ記事