Je me demandais quelle était exactement la différence entre
[[ $STRING != foo ]]
et
[ $STRING != foo ]
mis à part que ce dernier est conforme à la posix, trouvé dans sh et que le premier est une extension trouvée dans bash.
Je me demandais quelle était exactement la différence entre
[[ $STRING != foo ]]
et
[ $STRING != foo ]
mis à part que ce dernier est conforme à la posix, trouvé dans sh et que le premier est une extension trouvée dans bash.
Réponses:
Il y a plusieurs différences. À mon avis, quelques-uns des plus importants sont:
[
est un construit à Bash et de nombreux autres coquilles modernes. L'intégré [
est similaire à test
l'exigence supplémentaire d'une fermeture ]
. Les commandes intégrées [
et test
imitent la fonctionnalité /bin/[
et /bin/test
ainsi que leurs limites afin que les scripts seraient rétrocompatibles. Les exécutables d'origine existent toujours principalement pour la conformité POSIX et la compatibilité ascendante. L'exécution de la commande type [
dans Bash indique qu'il [
est interprété comme une fonction intégrée par défaut. (Remarque: which [
recherche uniquement les exécutables sur le PATH et équivaut à type -p [
)[[
n'est pas aussi compatible, cela ne fonctionnera pas nécessairement avec les /bin/sh
points. Il en [[
va de même pour l'option plus moderne de Bash / Zsh / Ksh.[[
est intégré au shell et qu’il n’a pas d’anciennes exigences, vous n'avez pas à vous soucier du fractionnement des mots basé sur la variable IFS pour perturber les variables qui donnent une chaîne contenant des espaces. Par conséquent, vous n'avez pas vraiment besoin de mettre la variable entre guillemets.Pour le reste, le reste n’est qu’une syntaxe plus agréable. Pour voir plus de différences, je recommande ce lien à une réponse à la FAQ: Quelle est la différence entre test, [et [[? . En fait, si vous êtes sérieux au sujet des scripts bash, je vous recommande de lire tout le wiki , y compris la FAQ, les pièges et le guide. La section de test de la section du guide explique également ces différences et explique pourquoi le ou les auteurs pensent qu'il [[
est préférable de choisir si vous n'avez pas à vous soucier d'être aussi portable. Les principales raisons sont:
< >
barres obliques inverses pour qu'elles ne soient pas évaluées comme une redirection d'entrée, ce qui peut gâcher certaines choses en écrasant des fichiers. Cela revient encore à [[
être un intégré. Si [(test) est un programme externe, le shell devrait faire une exception dans la manière dont il évalue <
et >
uniquement si /bin/test
est appelé, ce qui n'aurait pas vraiment de sens.En bref:
[est une bash Builtin
[[]] sont bash Mots-clés
Mots-clés: les mots-clés ressemblent beaucoup aux commandes intégrées, mais la principale différence est que des règles d'analyse syntaxiques spéciales leur sont applicables. Par exemple, [est une commande intégrée bash, tandis que [[est un mot clé bash. Ils sont tous les deux utilisés pour tester des choses, mais comme [[est un mot-clé plutôt qu'un mot-clé intégré, il bénéficie de quelques règles d'analyse particulières qui facilitent grandement les choses:
$ [ a < b ]
-bash: b: No such file or directory
$ [[ a < b ]]
Le premier exemple renvoie une erreur car bash tente de rediriger le fichier b vers la commande [a]. Le deuxième exemple fait ce que vous attendez. Le caractère <n'a plus sa signification particulière d'opérateur de redirection de fichier.
Source: http://mywiki.wooledge.org/BashGuide/CommandsAndArguments
[
est une commande shell POSIX; il n’est pas nécessaire de l’intégrer. ]
C’est simplement un argument que cette commande recherche, de sorte que la syntaxe est équilibrée. La commande est un synonyme pour test
sauf que test
cela ne cherche pas une fermeture ]
.
Différences de comportement
Quelques différences sur Bash 4.3.11:
Extension POSIX vs Bash:
[
est POSIX[[
est une extension Bash¹ documentée sur: https://www.gnu.org/software/bash/manual/bash.html#Conditional-Constructscommande régulière vs magie
[
est juste une commande régulière avec un nom étrange.
]
est juste un argument [
qui empêche d’utiliser d’autres arguments.
Ubuntu 16.04 a en réalité un exécutable /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, la <
redirection &&
et la ||
concaténation de plusieurs commandes ( )
génèrent des sous-shell, sauf s’ils sont échappés \
, et le développement du mot se déroule normalement.
[[ X ]]
est une construction unique qui permet d’ X
être analysé comme par magie. <
, &&
, ||
Et ()
sont traités spécialement, et les règles de séparation de mots sont différents.
Il y a aussi d'autres différences comme =
et =~
.
In Bashese: [
est une commande intégrée et [[
constitue 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. \
nécessaire ou bien la 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ée comme un séparateur de commande ANDcmd1 && 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 obsolète par POSIX{ [ a = a ] || [ a = b ]; } && [ a = b ]
Équivalent POSIX 5division 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, passe à [ 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, parce qu’il correspond aux modèles ( * ? [
sont magiques). 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 les mêmes dans les deux [
et [[
, mais ==
est une extension Bash.case ab in (a?) echo match; esac
: Équivalent POSIX[[ ab =~ 'ab?' ]]
: faux 4 , perd de la magie avec''
[[ ab? =~ 'ab?' ]]
: vrai=~
[[ ab =~ ab? ]]
: true, correspondance d' expression régulière POSIX étendue , ?
ne pas développer 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 : toujours utiliser []
.
Il y a des équivalents POSIX pour chaque [[ ]]
construction que j'ai vue.
Si vous vous utilisez [[ ]]
:
[
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 la coquille Korn
² 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"
travaille autour des deux.
³ et échoue également pour certaines valeurs de a
ou b
comme !
ou (
.
4 dans les versions 3.2 et supérieures et si la compatibilité avec la version 3.1 n'est pas activée (comme avec BASH_COMPAT=3.1
)
5 si le groupe (ici avec le {...;}
groupe de commande au lieu de ce (...)
qui irait à un sous - shell inutile) n'est pas nécessaire que les ||
et les &&
opérateurs de coque (par opposition aux ||
et les &&
[[...]]
opérateurs ou les -o
/ -a
[
opérateurs) ont la même priorité. Donc [ a = a ] || [ a = b ] && [ a = b ]
serait équivalent.
printf 'ab' | grep -Eq 'ab?'
dedans if [ … ]
?
if ( printf 'ab' | grep -Eq 'a' ); then echo 'a'; fi
. []
est une commande comme grep
. La commande ()
n'est peut-être pas nécessaire pour cette commande. Je ne suis pas sûr: je l'ai ajoutée à cause de la |
, dépend de la façon dont Bash analyse les choses. S'il n'y en avait pas, |
je suis sûr que vous pouvez écrire simplement if cmd arg arg; then
.
()
ça, ça semble: stackoverflow.com/questions/8965509/…
Single Bracket ie []
est compatible avec le shell POSIX pour inclure une expression conditionnelle.
Double Brackets, c’est-à [[]]
- dire une version améliorée (ou une extension) de la version POSIX standard, est pris en charge par bash et d’autres shells (zsh, ksh).
En bash, par comparaison numérique que nous utilisons eq
, ne
, lt
et gt
, avec deux supports de comparaison , nous pouvons utiliser ==
, !=
, <,
et >
littéralement.
[
est un synonyme de test command. Même s'il est intégré au shell, il crée un nouveau processus.[[
est une nouvelle version améliorée de celui-ci, 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
if
déclaration, voir mywiki.wooledge.org/BashPitfalls#if_.5Bgrep_foo_myfile.5D