シェルレベルの解釈で文字をエスケープする方法について話しているのではないことを明確にしたいと思います。
私が知る限り、エスケープする必要があるのは2文字のみです:%
および\
リテラル%
を出力するには、前に%
を付けてエスケープする必要があります。
printf '%%'
リテラル\
を出力するには、前に\
を付けてエスケープする必要があります。
printf '\\'
文字を文字通りに解釈するために文字をエスケープする必要がある他の例はありますか?
printf
のフォーマット引数では、%
と\
の文字のみが特殊です(いいえ、"
は特殊ではなく、\"
はPOSIXによって未指定です) 。
ただし、2つの重要な注釈があります。
ほとんどの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
これらのロケールはあらゆる種類のバグや脆弱性の原因となるため、これらのロケールの使用(およびインストール/使用可能にすること)を回避することをお勧めします。
一部の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}
。
_ yash
のprintf
ビルトインは、私が知っている唯一の例外です。
マニュアルから:
$ 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 '\"'
\"