web-dev-qa-db-fra.com

Différence entre les crochets simples et doubles dans Bash

Je lis des exemples bash sur if mais certains exemples sont écrits avec des crochets simples:

if [ -f $param ]
then
  #...
fi

d'autres avec doubles crochets:

if [[ $? -ne 0 ]]
then
    start looking for errors in yourlog
fi

Quelle est la différence?

139
rkmax

Célibataire [] sont des tests de condition conformes à posix shell.

Double [[]] sont une extension de la norme [] et sont pris en charge par bash et d’autres coques (par exemple, zsh, ksh). Ils supportent des opérations supplémentaires (ainsi que les opérations posix standard). Par exemple: || au lieu de -o et regex correspondant à =~. Une liste plus complète des différences peut être trouvée dans la section section du manuel de bash sur les constructions conditionnelles .

Utilisation [] quand vous voulez que votre script soit portable sur plusieurs shells. Utilisation [[]] si vous voulez des expressions conditionnelles non prises en charge par [] et n’a pas besoin d’être portable.

161
cmh

Différences de comportement

Testé dans Bash 4.3.11:

  • Extension POSIX vs Bash:

  • commande régulière vs magie

    • [ Est juste une commande normale avec un nom étrange.

      ] Est juste un argument de [ Qui empêche l'utilisation d'arguments supplémentaires.

      Ubuntu 16.04 a en réalité un exécutable pour celui-ci à /usr/bin/[ Fourni par coreutils, mais la version intégrée de bash est prioritaire.

      Rien ne change dans la manière dont Bash analyse la commande.

      En particulier, < Est une redirection, && Et || Concaténent plusieurs commandes, ( ) Génère des sous-shell à moins d'être échappé par \ Et le développement de Word. se passe comme d'habitude.

    • [[ X ]] Est une construction unique qui permet d'analyser X comme par magie. <, &&, || Et () Sont traités spécialement et les règles de fractionnement des mots sont différentes.

      Il y a aussi d'autres différences comme = Et =~.

      En bashese: [ Est une commande intégrée et [[ Est un mot clé: https://askubuntu.com/questions/445749/whats-the-difference-between -Shell-builtin-and-Shell-keyword

  • <

  • && Et ||

    • [[ a = a && b = b ]]: Vrai, logique et
    • [ a = a && b = b ]: Erreur de syntaxe, && Analysé comme un séparateur de commande AND cmd1 && cmd2
    • [ a = a -a b = b ]: Équivalent, mais déconseillé par POSIX³
    • [ a = a ] && [ b = b ]: POSIX et son équivalent fiable
  • (

    • [[ (a = a || a = b) && a = b ]]: faux
    • [ ( a = a ) ]: erreur de syntaxe, () est interprété comme un sous-shell
    • [ \( a = a -o a = b \) -a a = b ]: équivalent, mais () est obsolète par POSIX
    • { [ a = a ] || [ a = b ]; } && [ a = b ] Équivalent POSIX5
  • Fractionnement de mots et génération de nom de fichier lors des extensions (split + glob)

    • x='a b'; [[ $x = 'a b' ]]: True, les citations ne sont pas nécessaires
    • x='a b'; [ $x = 'a b' ]: Erreur de syntaxe, devient [ a b = 'a b' ]
    • x='*'; [ $x = 'a b' ]: Erreur de syntaxe s'il y a plus d'un fichier dans le répertoire actuel.
    • x='a b'; [ "$x" = 'a b' ]: Équivalent POSIX
  • =

    • [[ ab = a? ]]: True, car c'est le cas correspondance de motif (* ? [ Est magique). Ne développe pas globalement les fichiers du répertoire en cours.
    • [ ab = a? ]: a? Glob se développe. Donc, peut être vrai ou faux en fonction des fichiers dans le répertoire en cours.
    • [ ab = a\? ]: False, pas d'expansion globale
    • = Et == Sont identiques dans [ Et [[, Mais == Est une extension Bash.
    • case ab in (a?) echo match; esac: équivalent POSIX
    • [[ ab =~ 'ab?' ]]: False4, perd la magie avec ''
    • [[ ab? =~ 'ab?' ]]: True
  • =~

    • [[ ab =~ ab? ]]: True, POSIX expression régulière étendue correspondance, ? Ne se développe pas globalement
    • [ a =~ a ]: Erreur de syntaxe. Pas d'équivalent bash.
    • printf 'ab\n' | grep -Eq 'ab?': Équivalent POSIX (données sur une seule ligne)
    • awk 'BEGIN{exit !(ARGV[1] ~ ARGV[2])}' ab 'ab?': équivalent POSIX.

Recommandation : utilisez toujours [].

Il existe des équivalents POSIX pour chaque construction [[ ]] Que j'ai vue.

Si vous utilisez [[ ]] Vous:

  • perdre la portabilité
  • forcer le lecteur à apprendre les subtilités d'une autre extension bash. [ Est juste une commande régulière avec un nom étrange, aucune sémantique particulière n'est impliquée.

¹ Inspiré de la construction équivalente [[...]] Dans Korn Shell

² mais échoue pour certaines valeurs de a ou b (comme + Ou index) et effectue une comparaison numérique si a et b ressemble à des entiers décimaux. expr "x$a" '<' "x$b" Fonctionne autour des deux.

³ et échoue également pour certaines valeurs de a ou b comme ! Ou (.

4 dans bash 3.2 et supérieur et la compatibilité fournie avec bash 3.1 n'est pas activée (comme avec BASH_COMPAT=3.1)

5 bien que le groupement (ici avec le groupe de commandes {...;} au lieu de (...) qui exécuterait un sous-shell inutile) n'est pas nécessaire, car les opérateurs || et && (contrairement aux opérateurs || et &&[[...]] ou aux opérateurs -o/-a[) ont la même valeur priorité. Donc [ a = a ] || [ a = b ] && [ a = b ] Serait équivalent.

Entre parenthèses simples pour le test de condition (c.-à-d. [...]), certains opérateurs tels que single = est supporté par tous les shells, alors que l’opérateur == n'est pas pris en charge par certains des coquillages les plus anciens.

Dans les doubles crochets pour le test de condition (c'est-à-dire [[...]]), il n'y a pas de différence entre l'utilisation de = ou == dans des coquilles anciennes ou nouvelles.

Edit: Je devrais également noter que: Sous bash, utilisez toujours les doubles crochets [[...]] si possible, car ils sont plus sûrs que les crochets simples. Je vais illustrer pourquoi avec l'exemple suivant:

if [ $var == "hello" ]; then

si $ var est null/empty, c'est ce que le script voit:

if [ == "hello" ]; then

ce qui va casser votre script. La solution consiste à utiliser des doubles crochets ou à ne pas oublier de mettre des guillemets autour de vos variables ("$var"). Les doubles crochets constituent une meilleure pratique de codage défensif.

14
sampson-chen

[[ est un mot clé bash similaire à (mais plus puissant que) le [ commande.

Voir

http://mywiki.wooledge.org/BashFAQ/031 et http://mywiki.wooledge.org/BashGuide/TestsAndConditionals

Sauf si vous écrivez pour POSIX sh, nous vous recommandons [[.

10
Gilles Quenot

Manuel de Bash dit:

Lorsqu'ils sont utilisés avec [[ les opérateurs ‘<’ et ‘>’ trient lexicographiquement en utilisant les paramètres régionaux en cours. La commande de test utilise ASCII la commande.

(La commande de test est identique à [])

1
user5500105

vous pouvez utiliser les crochets doubles pour la correspondance des expressions rationnelles légères, par exemple. :

if [[ $1 =~ "foo.*bar" ]] ; then

(tant que la version de bash que vous utilisez supporte cette syntaxe)

1
asf107