web-dev-qa-db-ja.com

printfコマンドを使用するときにエスケープする必要がある文字は何ですか?

シェルレベルの解釈で文字をエスケープする方法について話しているのではないことを明確にしたいと思います。

私が知る限り、エスケープする必要があるのは2文字のみです:%および\

リテラル%を出力するには、前に%を付けてエスケープする必要があります。

printf '%%'

リテラル\を出力するには、前に\を付けてエスケープする必要があります。

printf '\\'

文字を文字通りに解釈するために文字をエスケープする必要がある他の例はありますか?

3
Harold Fischer

printfのフォーマット引数では、%\の文字のみが特殊です(いいえ、"は特殊ではなく、\"はPOSIXによって未指定です) 。

ただし、2つの重要な注釈があります。

  1. ほとんどのprintf実装¹では、特殊なのは\%のバイト値であり、POSIX仕様はprintfを必要とするため、それを必要と解釈することもできます。ユーティリティは、printf(3) C関数へのインターフェイスであり、たとえばwprintf(3)ではありません(たとえば 文字ではなく3バイトに切り捨てるには%.3sが必要です )。

    BIG5やGB18030などの一部の文字エンコードでは、バックスラッシュのエンコードを含む数百の文字があり、printfの文字をescapeするには、次のようにする必要があります。それらの文字のエンコーディング内の各\バイトの前に0x5cを挿入します!

    たとえば、BIG5-HKSCSでは、zh_HK.big5hkscs(香港)ロケールで使用されているように、Ěαжふ㘘㙡䓀䨵䪤么佢俞偅傜兝功吒吭园坼垥塿墦声娉娖娫嫹嬞孀尐岤崤幋廄惝愧揊擺暝枯柦槙檝歿汻沔涂淚滜潿瀙瀵焮燡牾狖獦珢珮琵璞疱癧礒稞穀笋箤糭綅縷罡胐胬脪苒茻莍蓋蔌蕚螏螰許豹贕赨跚踊蹾躡鄃酀酅醆鈾鎪閱鞸餐餤駹騱髏髢髿鱋鱭黠﹏????????????????????????????????????のすべてにバイト0x5c(\のエンコーディングでもある)が含まれています。

    ほとんどのprintf実装では、そのロケールでは、printf 'αb'αbを出力せず、バイト0xa3αのエンコーディングの最初のバイト)が出力されます。 BS文字(\bの拡張)。

    $ LC_ALL=zh_HK.big5hkscs luit
    $ locale charmap
    BIG5-HKSCS
    $ printf 'αb' | LC_ALL=C od -tx1 -tc
    0000000  a3  08
            243  \b
    0000002
    

    これらのロケールはあらゆる種類のバグや脆弱性の原因となるため、これらのロケールの使用(およびインストール/使用可能にすること)を回避することをお勧めします。

  2. 一部のprintf実装はオプションをサポートし、オプションの区切り文字として--をサポートする必要がないものもサポートします。したがって、printf ----を出力しませんが、フォーマット引数の欠落に関するエラーを報告する可能性があります。 format-で始まらないことを保証できない場合は、--オプション区切り文字を使用する必要があります。

     printf -- "$escaped_format" x y...
    

いずれにせよ、任意の文字列を出力したい場合は、次のようにします。

printf '%s\n' "$data" # with terminating newline
printf %s "$data"     # without

%sに渡される文字列に特別な文字はありません(printfの組み込みzshを除いて、NUL文字を渡すことはできません。 printf引数)。

リテラル\を入力する標準的な方法は\\を使用し、リテラル%%%を使用して入力しますが、ASCIIベースのシステムでは\134\45、および一部のprintf実装\x5c\x25、または\x{5c}\x{25}、または(非ASCIIの場合でも)システム):\u005c\u0025または\u{5c}\u{25}


_ yashprintfビルトインは、私が知っている唯一の例外です。

4

マニュアルから:

$ man printf
...
   printf FORMAT [ARGUMENT]...
...
   FORMAT controls the output as in C printf.  Interpreted sequences are:

これはいくつかの解釈されたシーケンスをリストします。以下は、キャラクター自体をエスケープする必要があるものです。

   \"     double quote
   \\     backslash
   %%     a single %

これら3つをbashでテストしましたが、期待どおりに動作しました。 man bash、このprintfの実装では、上記の「標準のprintf(1)形式の仕様」と、ここでは関係のないいくつかの実装を使用しています。


ただし、zshなどの他のシェルは、printfの実装が少し異なります。ここでは、二重引用符をエスケープしないでください。

$ printf '"'
"   
$ printf '\"'
\"
2
Sparhawk