web-dev-qa-db-ja.com

Bashの一重引用符と二重引用符の違い

Bashでは、一重引用符('')と二重引用符("")の違いは何ですか?

443
jrdioko

一重引用符は何も補間しませんが、二重引用符は補間します。例:変数、バッククォート、特定の\エスケープなど.

例:

$ echo "$(echo "upg")"
upg
$ echo '$(echo "upg")'
$(echo "upg")

Bashのマニュアルにはこう書かれています:

3.1.2.2一重引用符

文字を一重引用符(')で囲むと、引用符内の各文字のリテラル値が保持されます。バックスラッシュが前にあっても、単一引用符は単一引用符の間には現れないかもしれません。

3.1.2.3二重引用符

文字を二重引用符(")で囲むと、$`\、および履歴展開が有効な場合は!を除いて、引用符内のすべての文字のリテラル値が保持されます。文字$および`は、二重引用符内でそれらの特別な意味を保持します( シェル展開 を参照)。バックスラッシュは、$`"\、または改行のいずれかの文字が後に続く場合にのみ、特別な意味を保持します。二重引用符内では、これらの文字のいずれかが後に続くバックスラッシュは削除されます。特別な意味を持たない文字の前のバックスラッシュは変更されないままになります。二重引用符は、二重引用符の中にバックスラッシュを付けることによって引用符で囲むことができます。有効にすると、二重引用符で囲まれた!がバックスラッシュを使用してエスケープされない限り、履歴展開が実行されます。 !の前のバックスラッシュは削除されません。

二重引用符で囲まれている場合、特別なパラメータ*および@は特別な意味を持ちます( シェルパラメータの展開 を参照)。

452
Adam Batkin

何かをエコーし​​たときに何が起こるかについて言及しているのなら、二重引用符はそれらの間の変数を評価してその変数の値を出力するのに対し、二重引用符は文字通りエコーします。

たとえば、

#!/bin/sh
MYVAR=sometext
echo "double quotes gives you $MYVAR"
echo 'single quotes gives you $MYVAR'

これを与えるでしょう:

double quotes gives you sometext
single quotes gives you $MYVAR
208
likso

承認された回答 は素晴らしいです。トピックを素早く理解するのに役立つ表を作成しています。説明には、添字付き配列aと同様に単純変数arrも含まれます。

設定すれば

a=Apple      # a simple variable
arr=(Apple)  # an indexed array with a single element

そして2列目の式をechoすると、3列目に示すような結果/動作が得られます。 4列目は動作を説明しています。

 # | Expression  | Result      | Comments
---+-------------+-------------+--------------------------------------------------------------------
 1 | "$a"        | Apple       | variables are expanded inside ""
 2 | '$a'        | $a          | variables are not expanded inside ''
 3 | "'$a'"      | 'Apple'     | '' has no special meaning inside ""
 4 | '"$a"'      | "$a"        | "" is treated literally inside ''
 5 | '\''        | **invalid** | can not escape a ' within ''; use "'" or $'\'' (ANSI-C quoting)
 6 | "red$arocks"| red         | $arocks does not expand $a; use ${a}rocks to preserve $a
 7 | "redapple$" | redapple$   | $ followed by no variable name evaluates to $
 8 | '\"'        | \"          | \ has no special meaning inside ''
 9 | "\'"        | \'          | \' is interpreted inside "" but has no significance for '
10 | "\""        | "           | \" is interpreted inside ""
11 | "*"         | *           | glob does not work inside "" or ''
12 | "\t\n"      | \t\n        | \t and \n have no special meaning inside "" or ''; use ANSI-C quoting
13 | "`echo hi`" | hi          | `` and $() are evaluated inside ""
14 | '`echo hi`' | `echo hi`   | `` and $() are not evaluated inside ''
15 | '${arr[0]}' | ${arr[0]}   | array access not possible inside ''
16 | "${arr[0]}" | Apple       | array access works inside ""
17 | $'$a\''     | $a'         | single quotes can be escaped inside ANSI-C quoting
18 | "$'\t'"     | $'\t'       | ANSI-C quoting is not interpreted inside ""
19 | '!cmd'      | !cmd        | history expansion character '!' is ignored inside ''
20 | "!cmd"      | cmd args    | expands to the most recent command matching "cmd"
21 | $'!cmd'     | !cmd        | history expansion character '!' is ignored inside ANSI-C quotes
---+-------------+-------------+--------------------------------------------------------------------

また見なさい:

184
codeforester

他の人たちはとてもよく説明していて、単純な例を挙げたいと思います。

シェルが特殊文字を解釈しないように、テキストを一重引用符で囲むことができます。ドル記号、スペース、アンパーサンド、アスタリスク、およびその他の特殊文字は、一重引用符で囲むとすべて無視されます。

$ echo 'All sorts of things are ignored in single quotes, like $ & * ; |.' 

それはこれを与えるでしょう:

All sorts of things are ignored in single quotes, like $ & * ; |.

一重引用符で囲むことができない唯一のものは一重引用符です。

二重引用符は、二重引用符を使用してシェルでドル記号、逆引用符、および円記号を解釈できること以外は、一重引用符と同様に機能します。バックスラッシュは単一の特殊文字の解釈を妨げることがすでに知られています。ドル記号を変数の代わりにテキストとして使用する必要がある場合、これは二重引用符内で役立ちます。また、二重引用符をエスケープして、引用符付き文字列の末尾として解釈されないようにすることもできます。

$ echo "Here's how we can use single ' and double \" quotes within double quotes"

それはこれを与えるでしょう:

Here's how we can use single ' and double " quotes within double quotes

二重引用符の中では、アポストロフィ(そうでなければ引用符付きストリングの始まりと解釈される)は無視されることにも気付くかもしれません。ただし、変数は二重引用符で囲まれた値で解釈され、置き換えられます。

$ echo "The current Oracle SID is $Oracle_SID"

それはこれを与えるでしょう:

The current Oracle SID is test

バッククォートは、シングルクォーテーションやダブルクォーテーションと全く異なります。逆引用符は、特殊文字の解釈を防ぐために使用されるのではなく、実際にはそれらが囲むコマンドの実行を強制します。囲まれたコマンドが実行された後、それらの出力は元の行のバッククォートの代わりに置き換えられます。これは例でより明確になります。

$ today=`date '+%A, %B %d, %Y'`
$ echo $today 

それはこれを与えるでしょう:

Monday, September 28, 2015 
5
Sree

これはbashで引用符を扱う際の事実上の答えであるため、シェルで算術演算子を扱う場合、上記の答えを見逃した点をもう1つ追加します。

bashシェルは、算術演算を行う2つの方法をサポートしています。1つは組み込みのletコマンドと$((..))演算子で定義されています。前者は算術式を評価し、後者はより複雑なステートメントを評価します。

letで使用される算術式は、他のシェルコマンドと同様に、ワード分割、パス名拡張を行うことを理解することが重要です。そのため、適切な引用とエスケープを行う必要があります。

letを使用する場合は、この例を参照してください

let 'foo = 2 + 1'
echo $foo
3

ここで一重引用符を使用すると、ここで変数を展開する必要がないので、絶対に問題ありません。

bar=1
let 'foo = $bar + 1'

一重引用符の下の$barnotに展開され、二重引用符で囲む必要があるため、惨めに失敗します

let 'foo = '"$bar"' + 1'

これが理由の1つである必要があります。$((..))は常にletを使用することを考慮してください。その内部では、コンテンツがワード分割の対象にならないためです。 letを使用した前の例は、単純に次のように記述できます。

(( bar=1, foo = bar + 1 ))

常に一重引用符なしで$((..))を使用することを忘れないでください

$((..))は二重引用符で使用できますが、その結果として目的はありませんcannotには二重引用符が必要なコンテンツが含まれます。単一引用符で囲まないようにしてください。

printf '%d\n' '$((1+1))'
-bash: printf: $((1+1)): invalid number
printf '%d\n' $((1+1))
2
printf '%d\n' "$((1+1))"
2

単一引用符で囲まれた文字列内で$((..))演算子を使用する特別な場合には、演算子を引用符で囲まないままにするか、二重引用符で囲むように引用符を補間する必要があります。例えば。 curlステートメント内で演算子を使用して、リクエストが行われるたびにカウンターを渡すように結び付けている場合、

curl http://myurl.com --data-binary '{"requestCounter":'"$((reqcnt++))"'}'

ネストされた二重引用符を使用すると、リテラル文字列$((reqcnt++))requestCounterフィールドに渡されます。

1
Inian

' '" "の使用法には明確な違いがあります。

' 'が何にでも使われるとき、「変換または翻訳」は行われません。そのまま印刷されます。

" "では、それが囲むものは何でも、その値に「翻訳または変換」されます。

翻訳/変換とは、次のような意味です。一重引用符で囲まれたものはすべて、値に「翻訳」されません。彼らは引用符の中にあるように彼らは取られます。例:a=23の場合、echo '$a'は標準出力に$aを生成します。 echo "$a"は標準出力に23を生成します。

0
a_ran