Je lis des exemples bash if
mais certains exemples sont écrits avec des crochets simples:
if [ -f $param ]
then
#...
fi
d'autres avec des crochets doubles:
if [[ $? -ne 0 ]]
then
start looking for errors in yourlog
fi
Quelle est la différence?
bash
if-statement
rkmax
la source
la source
Réponses:
Les
[]
tests de condition conformes au shell posix sont simples .Double
[[]]
est une extension du standard[]
et est supporté par bash et d'autres shells (par exemple zsh, ksh). Ils prennent en charge des opérations supplémentaires (ainsi que les opérations standard posix). Par exemple:||
au lieu de-o
et regex correspondant à=~
. Une liste plus complète des différences peut être trouvée dans la section du manuel bash sur les constructions conditionnelles .Utilisez
[]
chaque fois que vous souhaitez que votre script soit portable entre les shells. À utiliser[[]]
si vous souhaitez que les expressions conditionnelles ne[]
soient pas prises en charge par et n'ont pas besoin d'être portables.la source
[[ ]]
(par exemple bash avec#!/bin/bash
ou#!/usr/bin/env bash
), vous devez utiliser l'option portable. Les scripts qui supposent que / bin / sh prend en charge des extensions comme celle-ci ne fonctionneront pas sur les systèmes d'exploitation comme les versions récentes de Debian et Ubuntu où ce n'est pas le cas.Différences de comportement
Testé dans Bash 4.3.11:
Extension POSIX vs Bash:
[
est POSIX[[
est une extension Bash¹ documentée à l' adresse : https://www.gnu.org/software/bash/manual/bash.html#Conditional-Constructscommande régulière vs magie
[
est juste une commande ordinaire avec un nom étrange.]
est juste un argument[
qui empêche l'utilisation d'autres arguments.Ubuntu 16.04 a en fait un exécutable
/usr/bin/[
fourni par coreutils, mais la version intégrée de bash a la priorité.Rien n'est modifié dans la manière dont Bash analyse la commande.
En particulier, la
<
redirection&&
et la||
concaténation de plusieurs commandes,( )
génèrent des sous-shell à moins d'être échappés par\
, et l'expansion des mots se produit comme d'habitude.[[ X ]]
est une construction unique qui permet d'X
être analysée par magie.<
,&&
,||
Et()
sont traités spécialement, et les règles de séparation de mots sont différents.Il existe également d'autres différences telles que
=
et=~
.En bashese:
[
est une commande intégrée, et[[
est un mot-clé: /ubuntu/445749/whats-the-difference-between-shell-builtin-and-shell-keyword<
[[ a < b ]]
: comparaison lexicographique[ a \< b ]
: Comme ci-dessus.\
requis ou effectue la redirection comme pour toute autre commande. Extension Bash.expr a \< b > /dev/null
: Équivalent POSIX², voir: Comment tester des chaînes pour lexicographique inférieur ou égal à Bash?&&
et||
[[ a = a && b = b ]]
: vrai, logique et[ a = a && b = b ]
: erreur de syntaxe,&&
analysée comme un séparateur de commande ANDcmd1 && cmd2
[ a = a -a b = b ]
: équivalent, mais obsolète par POSIX³[ a = a ] && [ b = b ]
: POSIX et équivalent fiable(
[[ (a = a || a = b) && a = b ]]
: faux[ ( a = a ) ]
: erreur de syntaxe,()
est interprétée comme un sous-shell[ \( a = a -o a = b \) -a a = b ]
: équivalent, mais()
obsolète par POSIX{ [ a = a ] || [ a = b ]; } && [ a = b ]
POSIX équivalent 5division de mot et génération de nom de fichier lors des expansions (split + glob)
x='a b'; [[ $x = 'a b' ]]
: vrai, les citations ne sont pas nécessairesx='a b'; [ $x = 'a b' ]
: erreur de syntaxe, se développe en[ a b = 'a b' ]
x='*'; [ $x = 'a b' ]
: erreur de syntaxe s'il y a plus d'un fichier dans le répertoire courant.x='a b'; [ "$x" = 'a b' ]
: Équivalent POSIX=
[[ ab = a? ]]
: vrai, car il fait des correspondances de motifs (* ? [
sont magiques). Ne s'étend pas globalement aux fichiers du répertoire actuel.[ ab = a? ]
:a?
glob se développe. Cela peut être vrai ou faux selon les fichiers du répertoire courant.[ ab = a\? ]
: faux, pas d'expansion globale=
et==
sont les mêmes dans les deux[
et[[
, mais==
est une extension Bash.case ab in (a?) echo match; esac
: Équivalent POSIX[[ ab =~ 'ab?' ]]
: false 4 , perd la magie avec''
[[ ab? =~ 'ab?' ]]
: vrai=~
[[ ab =~ ab? ]]
: true, correspondance d' expression régulière étendue POSIX ,?
ne se déplie 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 uniquement)awk 'BEGIN{exit !(ARGV[1] ~ ARGV[2])}' ab 'ab?'
: Équivalent POSIX.Recommandation : toujours utiliser
[]
.Il existe des équivalents POSIX pour chaque
[[ ]]
construction que j'ai vue.Si vous vous utilisez
[[ ]]
:[
est juste une commande ordinaire avec un nom étrange, aucune sémantique spéciale n'est impliquée.¹ Inspiré de la
[[...]]
construction équivalente dans le shell Korn² mais échoue pour certaines valeurs de
a
oub
(comme+
ouindex
) et effectue une comparaison numérique sia
etb
ressemble à des entiers décimaux.expr "x$a" '<' "x$b"
fonctionne autour des deux.³ et échoue également pour certaines valeurs de
a
oub
similaires!
ou(
.4 dans bash 3.2 et supérieur et à condition que la compatibilité avec bash 3.1 ne soit pas activée (comme avec
BASH_COMPAT=3.1
)5 bien que le regroupement (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 shell||
et&&
(par opposition aux opérateurs||
and&&
[[...]]
ou aux opérateurs-o
/-a
[
) ont la même priorité. Ce[ a = a ] || [ a = b ] && [ a = b ]
serait donc équivalent.la source
[]
doit être lue comme ma préférence : utiliser[]
si vous ne voulez pas perdre la portabilité . Comme indiqué ici : Si la portabilité / la conformité à POSIX ou au BourneShell est un problème, l'ancienne syntaxe doit être utilisée. Si d'un autre côté le script nécessite BASH, Zsh ou KornShell, la nouvelle syntaxe est généralement plus flexible, mais pas nécessairement rétrocompatible. Je préfère aller avec[[ ab =~ ab? ]]
si je peux et ne pas me soucier de la compatibilité descendante queprintf 'ab' | grep -Eq 'ab?'
À l'intérieur de simples crochets pour le test de condition (c'est-à-dire [...]), certains opérateurs tels que single
=
sont supportés par tous les shells, alors que l'utilisation d'opérateur==
n'est pas supportée par certains des shells plus anciens.À l'intérieur des doubles crochets pour le test de condition (c'est-à-dire [[...]]), il n'y a aucune différence entre l'utilisation
=
ou==
dans des shells anciens ou nouveaux.Edit: Je devrais aussi noter que: Dans bash, utilisez toujours des doubles crochets [...] si possible, car c'est plus sûr que les simples crochets. Je vais illustrer pourquoi avec l'exemple suivant:
si $ var est nul / vide, alors c'est ce que voit le script:
ce qui cassera votre script. La solution consiste soit à utiliser des doubles crochets, soit à toujours penser à mettre des guillemets autour de vos variables (
"$var"
). Les doubles crochets sont une meilleure pratique de codage défensif.la source
[[
est un mot-clé bash similaire (mais plus puissant que) la[
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
[[
.la source
vous pouvez utiliser les doubles crochets pour la correspondance des expressions régulières légères, par exemple:
if [[ $1 =~ "foo.*bar" ]] ; then
(tant que la version de bash que vous utilisez prend en charge cette syntaxe)
la source
Le manuel de Bash dit:
(La commande de test est identique à [])
la source