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?
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.
Différences de comportement
Testé dans Bash 4.3.11:
Extension POSIX vs Bash:
[
est POSIX[[
Est une extension Bash¹ documentée à l'adresse suivante: https://www.gnu.org/software/bash/manual/bash.html#Conditional-Constructscommande 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
<
[[ a < b ]]
: Comparaison lexicographique[ a \< b ]
: Comme ci-dessus. \
Requis ou sinon, la redirection, comme pour toute autre commande. Extension Bash.expr a \< b > /dev/null
: Équivalent POSIX², voir: Comment tester des chaînes lexicographiques inférieures ou égales dans Bash?&&
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 POSIX5Fractionnement 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écessairesx='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:
[
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.
[[
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 [[
.
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 à [])
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)