時々私はスクリプトがいくつかのテキストを引用し、これらのさまざまな方法のすべてを使用して参照してください"..."
、'...'
、$'...'
、と$"..."
。なぜ非常に多くの種類の引用が使用されているのですか?
それらは異なる振る舞いをしたり、それらの中で私ができることに影響を与えますか?
時々私はスクリプトがいくつかのテキストを引用し、これらのさまざまな方法のすべてを使用して参照してください"..."
、'...'
、$'...'
、と$"..."
。なぜ非常に多くの種類の引用が使用されているのですか?
それらは異なる振る舞いをしたり、それらの中で私ができることに影響を与えますか?
回答:
これらはすべて異なるものを意味し、その中に異なるもの(または異なる意味を持つ同じもの)を書くことができます。異なる種類の引用符は\something
、その中の異なるエスケープシーケンスを解釈する()か、変数の補間($something
)およびその他の種類の展開を許可するかしないかを指定します。
要するに:
'...'
完全にリテラルです。"..."
変数と埋め込み引用符文字の両方を許可します。 $'...'
のような文字エスケープを実行しますが\n
、変数を展開しません。$"..."
Bashとkshでの人間の言語の翻訳用です。単一引用符の間に書くものはすべて文字通り処理され、まったく処理されません。バックスラッシュとドル記号には特別な意味はありません。つまり、文字(他の一重引用符を含む!)をバックスラッシュでエスケープしたり、変数を補間したり、その他のシェル機能を使用したりすることはできません。
これらの例はすべて、引用符の間に文字通り書かれたものになります。
'hello world' => hello world
'/pkg/bin:$PATH' => /pkg/bin:$PATH
'hello\nworld' => hello\nworld
'`echo abc`' => `echo abc`
'I\'dn\'t've' => I\dn'tve
最後のものは複雑です- 引用符で囲まれていないテキストと一緒に実行される2つの単一引用符で囲まれた文字列があります。最初のものにはが含まれますI\
。引用符で囲まdn\'t
れていないテキストには、シェルレベルでエスケープされた単一引用符が含まれているため、引用符で囲まれた文字列を開始せず、リテラル文字として含まれています(so、dn't
)。最後の引用文字列はだけve
です。これらはすべて、シェルの通常の動作方法で1つの単語にまとめられます。
リテラルテキストと変数を組み合わせるためのやや一般的なイディオムは、次のように一緒に実行することです。
'let x="'$PATH\"
になります
let x="/usr/bin:/bin"
単一の単語として($PATH
場合によっては二重引用符の方が適切です - 変数値のスペースまたはグロビング文字は別の方法で処理されます -しかし、読みやすい実行例のために私はしていません)。
二重引用符内では、2種類の展開が処理されます。バックスラッシュを使用して文字をエスケープし、展開またはエスケープが処理されないようにすることができます。
二重引用符内で発生する展開の2つのカテゴリがあります。
$
(パラメーター展開$abc
and${abc}
、コマンド置換$(...)
、算術展開$((...))
)で始まるもの;`abc`
;引用符の中では、円記号は$
orの前に置くことでそれらの展開を禁止でき`
ます。二重引用符をエスケープすることもできるため、文字列または別のバックスラッシュに\"
含めることができ"
ます。他のバックスラッシュは文字通り保存されます-他の文字を生成するためのエスケープはなく、削除されません。
これらの例の中には、以前とは異なる動作をするものとそうでないものがあります。
"hello world" => hello world
"/pkg/bin:$PATH" => /pkg/bin:/bin:/usr/bin
"hello\nworld" => hello\nworld
"hello\\nworld" => hello\nworld
"`echo abc`" => abc
"I\'dn\'t've" => I\'dn\'t've
"I'dn't've" => I'dn't've
"I\"dn\"t've" => I"dn"t've
このようなクォートにより、Cスタイルのバックスラッシュエスケープを処理できますが、埋め込み変数または置換はできません。これは、文字エスケープをサポートする唯一の種類の引用です。
これはkshの拡張機能であり、Bash、zsh、およびその他のシェルでもサポートされるようになりました。これはまだ POSIX標準の一部ではないため、最大限に移植可能なスクリプトでは使用できませんが、Bashまたはkshスクリプトは自由に使用できます。
これらのエスケープのすべてのCの意味で使用することができます:\a
、\b
、\f
、\n
、\r
、\t
、\v
、およびリテラルエスケープ\\
、\'
、\"
、と\?
。また、拡張機能\e
(エスケープ文字)とBashおよびksh \cx
(Ctrl-xで入力されるもの、たとえば\cM
キャリッジリターン)もサポートします。シェルには、独自のさまざまなマイナー拡張機能があります。
また、4種類の一般的な文字エスケープが可能です。
\nnn
、8進数値nnnの単一バイト\xHH
、16進値HHの単一バイト\uHHHH
、16進インデックスがHHHHであるUnicodeコードポイント\UHHHHHHHH
、16進インデックスがHHHHHHHHであるUnicodeコードポイントこれらの数字はすべて、最初の数字の後のオプションです。
$
そして、`
意味がありませんし、あなたが変数そこを含めることはできませんので、文字通りに保存されています。
$'hello world' => hello world
$'/pkg/bin:$PATH' => /pkg/bin:$PATH
$'hello\nworld' => hello
world
$'`echo abc`' => `echo abc`
$'I\'dn\'t\'ve' => I'dn't've
$'\U1f574\u263A' => 🕴☺
これらのほとんどは、あなたが使用してシミュレートすることができエスケープコマンドを POSIXにのみ必要ですが、、、、、、、、、およびそこに仕事に。必要に応じて、コマンド置換を使用して二重引用符を埋め込むことができます。printf
\\
\a
\b
\f
\n
\r
\t
\v
\nnn
printf
"Path:$(printf '\t')$PATH"
これは、自然言語のテキスト文字列をローカライズするためのkshおよびBash固有の拡張機能であり、メッセージカタログ内の引用符内の部分を検索します。最初にすべての二重引用符展開を実行します。文字列が翻訳データベースで見つからない場合、それは独自の翻訳として使用されます。組み込みの前提は、文字列が英語であるということです。
おそらくこれを使いたくはないでしょうが、もし見たなら、通常は通常の二重引用符として扱うことができます。
注意すべき点の1つは、埋め込みパラメーターの展開と埋め込み文字のエスケープの両方を許可するクォートはないということです。あなたがそれを望むほとんどの場合、以下を使用する方が安全printf
です:
printf 'New path: \e[1m%s\e[0m' "/pkg/bin:$PATH:"
これにより、文字エスケープの対象となる部分とデータ値である部分が明確に区別されます。
もう1つは、二重引用符内で配列拡張が使用されない限り 、これらのスタイルの引用のすべてがシェルで単一の「単語」を作成することです。どちらの単一引用符形式も常に1つの単語であり、それ以上展開されることはありません。$@
${x[@]}
$"..."
2.0でbashに追加されたksh93からでもあります。
\cX
ではzsh
。それはだ\CX
か\C-X
が(\c
すでに特別な意味を持つecho
)
'let x="'$PATH\"
引用符で囲まzsh
れ$PATH
ていない以外のシェルのリストコンテキストでは間違っています(したがって、ここでは不要なsplit + globの影響を受けます)。