Je me demandais quelle était exactement la différence entre
[[ $STRING != foo ]]
et
[ $STRING != foo ]
est, à part que ce dernier est compatible posix, trouvé dans sh et le premier est une extension trouvée dans bash.
Il existe plusieurs différences. À mon avis, quelques-uns des plus importants sont:
[
est intégré à Bash et à de nombreux autres shells modernes. La fonction [
est similaire à test
avec l'exigence supplémentaire d'une fermeture ]
. Les builtins [
et test
imitent la fonctionnalité /bin/[
et /bin/test
ainsi que leurs limitations afin que les scripts soient rétrocompatibles. Les exécutables d'origine existent toujours principalement pour la conformité POSIX et la compatibilité descendante. Exécution de la commande type [
dans Bash indique que [
est interprété comme une fonction intégrée par défaut. (Remarque: which [
ne recherche que les exécutables sur le chemin [~ # ~] [~ # ~] et est équivalent à type -p [
)[[
n'est pas aussi compatible, il ne fonctionnera pas nécessairement avec quoi que ce soit /bin/sh
pointe vers. Donc [[
est le plus moderne Bash/Zsh/Ksh option.[[
est intégré au Shell et n'a pas d'exigences héritées, vous n'avez pas à vous soucier du fractionnement de Word basé sur les [~ # ~] ifs [~ # ~] variable pour gâcher les variables évaluées en une chaîne avec des espaces. Par conséquent, vous n'avez pas vraiment besoin de mettre la variable entre guillemets.Pour la plupart, le reste n'est qu'une syntaxe plus agréable. Pour voir plus de différences, je recommande ce lien vers une FAQ réponse: Quelle est la différence entre test, [et [[? . En fait, si vous êtes sérieux) à propos des scripts bash, je recommande de lire l'intégralité wiki , y compris la FAQ, Pièges , et le Guide. La section de test de la section guide explique ces différences aussi, et pourquoi les auteurs pensent [[
est un meilleur choix si vous n'avez pas à vous soucier d'être aussi portable. Les principales raisons sont:
< >
avec des barres obliques inverses afin de ne pas les évaluer en tant que redirection d'entrée, ce qui peut vraiment gâcher certaines choses en écrasant les fichiers. Cela remonte à nouveau à [[
étant une fonction intégrée. Si [(test) est un programme externe, le Shell devra faire une exception dans la façon dont il évalue <
et >
seulement si /bin/test
est appelé, ce qui n'aurait pas vraiment de sens.En bref:
[est un bash Builtin
[[]] sont bash Mots-clés
Mots-clés: Les mots-clés sont tout à fait comme des prédéfinis, mais la principale différence est que des règles d'analyse spéciales leur sont applicables. Par exemple, [est un code bash intégré, tandis que [[est un mot clé bash. Ils sont tous deux utilisés pour tester des trucs, mais comme [[est un mot-clé plutôt qu'une fonction intégrée, il bénéficie de quelques règles d'analyse spéciales qui le rendent beaucoup plus facile:
$ [ a < b ]
-bash: b: No such file or directory
$ [[ a < b ]]
Le premier exemple renvoie une erreur car bash essaie de rediriger le fichier b vers la commande [a]. Le deuxième exemple fait réellement ce que vous attendez de lui. Le caractère <n'a plus sa signification particulière d'opérateur de redirection de fichiers.
Source: http://mywiki.wooledge.org/BashGuide/CommandsAndArguments
Différences de comportement
Quelques différences sur Bash 4.3.11:
Extension POSIX vs Bash:
[
est POSIX[[
Est une extension Bash¹ documentée à: 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.
]
N'est qu'un argument de [
Qui empêche l'utilisation d'autres arguments.
Ubuntu 16.04 a en fait un exécutable pour cela à /usr/bin/[
Fourni par coreutils, mais la version bash intégrée a priorité.
Rien n'est modifié dans la façon dont Bash analyse la commande.
En particulier, <
Est une redirection, &&
Et ||
Concaténent plusieurs commandes, ( )
Génère des sous-coquilles à moins que \
N'échappe, et l'expansion de Word arrive comme d'habitude.
[[ X ]]
Est une construction unique qui permet d'analyser magiquement X
. <
, &&
, ||
Et ()
Sont traités spécialement, et les règles de fractionnement de Word sont différentes.
Il existe également 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 bien fait une redirection comme pour toute autre commande. Extension Bash.expr a \< b > /dev/null
: Équivalent POSIX², voir: https://stackoverflow.com/questions/21294867/how-to-test-strings-for-lexicographic-less-than-or-equal-in- bash/52707989 # 52707989&&
Et ||
[[ a = a && b = b ]]
: Vrai, logique et[ a = a && b = b ]
: Erreur de syntaxe, &&
Analysé comme séparateur de commande AND cmd1 && cmd2
[ a = a -a b = b ]
: Équivalent, mais déconseillé 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é comme un sous-shell[ \( a = a -o a = b \) -a a = b ]
: équivalent, mais ()
est déconseillé 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' ]]
: Vrai, les guillemets 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 le fait correspondance de motifs (* ? [
Est magique). N'étend pas les fichiers glob dans le répertoire en cours.[ ab = a? ]
: a?
Glob se développe. Cela peut donc être vrai ou faux selon les fichiers du répertoire courant.[ ab = a\? ]
: Faux, pas une expansion globale=
Et ==
Sont les mêmes dans [
Et [[
, Mais ==
Est une extension Bash.case ab in (a?) echo match; esac
: équivalent POSIX[[ ab =~ 'ab?' ]]
: Faux4, perd de la magie avec ''
[[ ab? =~ 'ab?' ]]
: Vrai=~
[[ ab =~ ab? ]]
: Vrai, POSIX expression régulière étendue correspond, ?
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 y a 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 spéciale n'est impliquée.¹ Inspiré de la construction [[...]]
Équivalente dans le 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 nombres 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 regroupement (ici avec le groupe de commandes {...;}
au lieu de (...)
qui exécuterait un sous-shell inutile) ne soit pas nécessaire car les opérateurs Shell ||
et &&
(contrairement aux opérateurs ||
et &&
[[...]]
ou aux opérateurs -o
/-a
[
) ont la même valeur priorité. [ a = a ] || [ a = b ] && [ a = b ]
Serait donc équivalent.
support simple c'est-à-dire []
est compatible avec POSIX Shell pour inclure une expression conditionnelle.
Supports doubles c'est-à-dire [[]]
est une version améliorée (ou extension) de la version POSIX standard, prise en charge par bash et d'autres shells (zsh, ksh).
En bash, pour la comparaison numérique, nous utilisons eq
, ne
, lt
et gt
, avec des crochets doubles pour la comparaison, nous pouvons utiliser ==
, !=
, <,
et >
au sens propre.
[
est un synonyme de commande de test. Même s'il est intégré au Shell, il crée un nouveau processus.[[
en est une nouvelle version améliorée, qui est un mot-clé, pas un programme.par exemple:
[ var1 lt var2] #works
[ var1 < var2] #error: var2 No such file or directory
[ var1 \< var2] #works with escape
[[ var1 < var2]] #works
Sur la base d'une lecture rapide des sections pertinentes de la page de manuel, la principale différence semble être que le ==
et !=
les opérateurs correspondent à un modèle, plutôt qu'à une chaîne littérale, et il y a aussi le =~
Opérateur de comparaison d'expressions régulières.