web-dev-qa-db-fra.com

Différence entre guillemets simples et doubles dans Bash

Dans Bash, quelles sont les différences entre guillemets simples ('') et doubles guillemets ("")?

401
jrdioko

Les guillemets simples n'interpolent rien, mais les guillemets doubles. Par exemple: variables, backticks, certaines échappements \, etc. 

Exemple:

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

Le manuel de Bash dit ceci:

3.1.2.2 Citations uniques

Le fait de placer des caractères entre guillemets simples (') préserve la valeur littérale de chaque caractère entre guillemets. Un seul guillemet ne peut pas apparaître entre guillemets, même s'il est précédé d'une barre oblique inverse. 

3.1.2.3 Citations doubles

Les caractères entre guillemets (") préservent la valeur littérale de tous les caractères entre guillemets, à l'exception de $, `, \ et, lorsque le développement de l'historique est activé, !. Les caractères $ et ` conservent leur signification particulière entre guillemets (voir Shell Expansions ). La barre oblique inverse ne conserve sa signification particulière que si l'un des caractères suivants est suivi: $, `, ", \ ou une nouvelle ligne. Dans les guillemets doubles, les barres obliques inverses suivies de l'un de ces caractères sont supprimées. Les barres obliques inverses précédant des caractères sans signification particulière sont laissées telles quelles. Une citation double peut être citée entre guillemets en la faisant précéder d'une barre oblique inverse. Si activé, l'expansion de l'historique sera effectuée à moins qu'un ! apparaissant entre guillemets ne soit échappé à l'aide d'une barre oblique inverse. La barre oblique inverse précédant le ! n'est pas supprimée.

Les paramètres spéciaux * et @ ont une signification particulière entre guillemets (voir Shell Parameter Expansion ). 

430
Adam Batkin

Si vous faites référence à ce qui se passe lorsque vous faites écho à quelque chose, les guillemets simples vont littéralement faire écho à ce que vous avez entre eux, alors que les guillemets doubles évalueront les variables entre eux et afficheront la valeur de la variable.

Par exemple, cela

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

donnera ceci:

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

La réponse acceptée est excellente. Je fais un tableau qui aide à la compréhension rapide du sujet. L'explication implique une variable simple a ainsi qu'un tableau indexé arr.

Si on met

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

et ensuite echo l'expression dans la deuxième colonne, nous obtiendrions le résultat/comportement indiqué dans la troisième colonne. La quatrième colonne explique le comportement.

 # | 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 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"
---+-------------+-------------+--------------------------------------------------------------------

Voir également:

165
codeforester

D'autres ont très bien expliqué et veulent juste donner des exemples simples.

Les guillemets simples peuvent être utilisés autour du texte pour empêcher le shell d'interpréter les caractères spéciaux. Les signes dollar, les espaces, les esperluettes, les astérisques et autres caractères spéciaux sont tous ignorés lorsqu'ils sont placés entre guillemets simples.

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

Cela donnera ceci:

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

La seule chose qui ne puisse pas être placée entre guillemets simples est un guillemet simple.

Les guillemets doubles agissent de la même manière que les guillemets simples, sauf que les guillemets permettent toujours à Shell d’interpréter les signes dollar, les guillemets arrières et les barres obliques inverses. On sait déjà que les antislash empêchent l’interprétation d’un seul caractère spécial. Cela peut être utile entre guillemets doubles si un signe dollar doit être utilisé comme texte plutôt que comme variable. Cela permet également aux guillemets doubles d'être échappés afin qu'ils ne soient pas interprétés comme la fin d'une chaîne citée.

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

Cela donnera ceci:

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

Vous remarquerez également que l'apostrophe, qui autrement serait interprétée comme le début d'une chaîne entre guillemets, est ignorée entre guillemets doubles. Les variables, cependant, sont interprétées et remplacées par leurs valeurs entre guillemets doubles.

$ echo "The current Oracle SID is $Oracle_SID"

Cela donnera ceci:

The current Oracle SID is test

Les guillemets arrières sont totalement différents des guillemets simples ou doubles. Au lieu d’être utilisées pour empêcher l’interprétation de caractères spéciaux, les guillemets arrières forcent en réalité l’exécution des commandes qu’ils renferment. Une fois les commandes incluses exécutées, leur sortie est remplacée par les guillemets arrières de la ligne d'origine. Ce sera plus clair avec un exemple.

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

Cela donnera ceci:

Monday, September 28, 2015 
4
Sree

Comme il s’agit de la réponse de facto lorsqu’il s’agit de guillemets dans bash, j’ajouterai un point qui n’a pas été retenu dans les réponses ci-dessus, lorsqu’il s’agit des opérateurs arithmétiques de Shell.

Le shell bash prend en charge les opérations arithmétiques de deux manières, l'une définie par la commande let intégrée et l'opérateur $((..)). Le premier évalue une expression arithmétique tandis que le second est plutôt une déclaration composée.

Il est important de comprendre que l'expression arithmétique utilisée avec let subit une expansion par fractionnement de Word et par chemin d'accès, comme toutes les autres commandes du shell. Il faut donc bien citer et s’échapper. 

Voir cet exemple lorsque vous utilisez let

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

Utiliser des guillemets simples ici est tout à fait correct ici, car il n’est pas nécessaire d’agrandir de manière variable ici, considérons le cas suivant:

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

échouerait misérablement, car le $bar sous guillemets simples pas se développerait et devait être mis entre guillemets

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

Cela devrait être l’une des raisons, la $((..)) devrait toujours être considérée au-dessus de l’utilisation de let. Parce qu'à l'intérieur, le contenu n'est pas sujet à la division de Word. L’exemple précédent utilisant let peut être simplement écrit ainsi:

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

Rappelez-vous toujours d'utiliser $((..)) sans guillemets simples

Bien que $((..)) puisse être utilisé avec des guillemets doubles, il n'a aucune utilité, car son résultat ne peut pas contenir un contenu qui aurait besoin de la guillemet double. Assurez-vous simplement qu'il ne soit pas cité individuellement.

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

Dans certains cas particuliers, lorsque vous utilisez l’opérateur $((..)) dans une seule chaîne de citation, vous devez interpoler les guillemets de manière à ce que l’opérateur soit laissé sans guillemets ou entre guillemets. Par exemple. Si vous envisagez d'utiliser l'opérateur dans une instruction curl pour transmettre un compteur chaque fois qu'une demande est faite, envisagez un cas particulier.

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

Notez l'utilisation de guillemets doubles imbriqués, sans lesquels la chaîne littérale $((reqcnt++)) est transmise au champ requestCounter.

1
Inian

Il existe une distinction claire entre l'utilisation de ' ' et de " "

Lorsque ' ' est utilisé autour de quoi que ce soit, aucune "transformation ou traduction" n'est effectuée. C'est imprimé tel quel. 

Avec " ", tout ce qu’il entoure est "traduit ou transformé" en sa valeur. 

Par traduction/transformation, j'entends ce qui suit: Rien dans les guillemets simples ne sera "traduit" en leurs valeurs. Ils seront pris comme ils sont entre guillemets. Exemple: a=23, alors echo '$a' produira $a sur la sortie standard. Alors que echo "$a" produira 23 sur la sortie standard.

0
a_ran