Je me demandais juste quelle était la différence exacte entre
[[ $STRING != foo ]]
et
[ $STRING != foo ]
est, à part que le dernier est conforme à POSIX, trouvé dans sh et le premier est une extension trouvée dans bash.
Je me demandais juste quelle était la différence exacte entre
[[ $STRING != foo ]]
et
[ $STRING != foo ]
est, à part que le dernier est conforme à POSIX, trouvé dans sh et le premier est une extension trouvée dans bash.
Il existe plusieurs différences. À mon avis, quelques-unes des plus importantes sont :
[
est un module intégré à Bash et à de nombreux autres shells modernes. Le module intégré [
est similaire à test
avec l'exigence supplémentaire d'une clôture ]
. Les builtins [
y test
imiter la fonctionnalité /bin/[
y /bin/test
ainsi que leurs limitations afin que les scripts soient rétrocompatibles. Les exécutables originaux existent toujours, principalement pour la conformité POSIX et la compatibilité ascendante. L'exécution de la commande type [
dans Bash indique que [
est interprété comme un builtin par défaut. (Note : which [
ne recherche que les exécutables sur le PATH et est équivalent à type -P [
. Vous pouvez exécuter type --help
pour plus de détails)[[
n'est pas aussi compatible, il ne fonctionnera pas nécessairement avec ce que l'on appelle le "système". /bin/sh
pointe vers. Donc [[
est l'option plus moderne de Bash / Zsh / Ksh.[[
est intégré dans le Shell et n'a pas d'exigences en matière d'héritage, vous n'avez pas à vous soucier de la séparation des mots en fonction de l'élément IFS pour se tromper sur les variables qui évaluent une chaîne de caractères avec des espaces. Par conséquent, vous n'avez pas vraiment besoin de mettre la variable entre guillemets.Pour l'essentiel, le reste n'est qu'une syntaxe plus agréable. Pour voir plus de différences, je recommande ce lien vers une réponse de la FAQ : [Quelle est la différence entre test, [ et [[ ?](http://mywiki.wooledge.org/BashFAQ/031) . En fait, si vous êtes sérieux au sujet des scripts bash, je vous recommande de lire l'intégralité de l'ouvrage wiki y compris la FAQ, Pièges et Guide. La section test de la section guide explique également ces différences et les raisons pour lesquelles les auteurs pensent que [[
est un meilleur choix si vous n'avez pas besoin de vous soucier d'être aussi portable. Les principales raisons sont :
< >
avec des backslashes afin qu'ils ne soient pas évalués comme une redirection d'entrée, ce qui peut vraiment mettre le bazar en écrasant des fichiers. Ceci nous ramène encore une fois à [[
étant un buildin. Si [ (test) est un programme externe, le Shell devrait faire une exception dans la façon dont il évalue <
y >
seulement si /bin/test
est appelé, ce qui n'aurait pas vraiment de sens.
Merci, le lien vers la FAQ bash était ce que je cherchais (je ne connaissais pas cette page, merci).
J'ai édité votre post avec cette information, mais [ et test sont exécutés en tant que builtins. Les builtins ont été conçus pour remplacer /bin/[ et /bin/test mais devaient également reproduire les limitations des binaires. La commande 'type [' vérifie que le buildin est utilisé. La commande 'which [' recherche uniquement les exécutables dans le PATH et est équivalente à 'type -P ['.
En bref :
[ est un bash Builtin
[[ ]] sont bash Mots clés
Mots-clés : Les mots-clés sont assez semblables aux builtins, mais la principale différence est que des règles d'analyse spéciales s'appliquent à eux. Par exemple, [ est un buildin bash, alors que [[ est un mot-clé bash. Ils sont tous deux utilisés pour tester des choses, mais comme [[ est un mot-clé plutôt qu'un buildin, 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 tente de rediriger le fichier b vers la commande [ a ]. Le deuxième exemple fait en fait ce que vous attendez de lui. Le caractère < n'a plus sa signification spéciale d'opérateur de redirection de fichier.
Source : http://mywiki.wooledge.org/BashGuide/CommandsAndArguments
[
est une commande POSIX Shell ; elle ne doit pas être intégrée. ]
est juste un argument que cette commande recherche, afin que la syntaxe soit équilibrée. La commande est un synonyme de test
sauf que test
ne cherche pas à conclure ]
.
Différences de comportement
Quelques différences sur Bash 4.3.11 :
Extension POSIX vs Bash :
[
est POSIX
[[
est une extension de Bash inspiré de Korn Shellcommandement régulier contre magie
[
est juste une commande normale avec un nom bizarre.
]
est juste le dernier argument de [
.
Ubuntu 16.04 dispose d'un exécutable pour ce programme à l'adresse suivante /usr/bin/[
fourni par coreutils mais la version intégrée de bash est prioritaire.
Rien n'est modifié dans la façon dont Bash analyse la commande.
En particulier, <
est la redirection, &&
y ||
concaténer plusieurs commandes, ( )
génère des sous-coquilles, sauf si elles sont échappées par \
et l'expansion des mots se fait comme d'habitude.
[[ X ]]
est une construction unique qui rend X
être analysé comme par magie. <
, &&
, ||
y ()
font l'objet d'un traitement spécial, et les règles de division des mots sont différentes.
Il existe également d'autres différences comme =
y =~
.
En bachique : [
est une commande intégrée, et [[
est un mot-clé : https://askubuntu.com/questions/445749/whats-the-difference-between-Shell-builtin-and-Shell-mot-clé
<
[[ a < b ]]
: comparaison lexicographique[ a \< b ]
: Même chose que ci-dessus. \
nécessaire ou sinon fait une redirection comme pour toute autre commande. Extension Bash.expr x"$x" \< x"$y" > /dev/null
o [ "$(expr x"$x" \< x"$y")" = 1 ]
: Les équivalents POSIX, voir : https://stackoverflow.com/questions/21294867/how-to-test-strings-for-lexicographic-less-than-or-equal-in-bash/52707989#52707989
&&
y ||
[[ a = a && b = b ]]
: vrai, logique et
[ a = a && b = b ]
: erreur de syntaxe, &&
interprété comme un séparateur de commande AND cmd1 && cmd2
[ a = a ] && [ b = b ]
: équivalent fiable POSIX[ a = a -a b = b ]
: presque équivalent, mais déprécié par POSIX car il est insensé et échoue pour certaines valeurs de a
o b
comme !
o (
qui seraient interprétés comme des opérations logiques(
[[ (a = a || a = b) && a = b ]]
: faux. Sans ( )
serait vrai parce que [[ && ]]
a une plus grande priorité que [[ || ]]
[ ( a = a ) ]
: erreur de syntaxe, ()
est interprétée comme une sous-couche[ \( a = a -o a = b \) -a a = b ]
: équivalent, mais ()
, -a
y -o
sont dépréciés par POSIX. Sans \( \)
serait vrai parce que -a
a une plus grande priorité que -o
{ [ a = a ] || [ a = b ]; } && [ a = b ]
équivalent POSIX non déprécié. Dans ce cas particulier cependant, nous aurions pu écrire juste : [ a = a ] || [ a = b ] && [ a = b ]
parce que le ||
y &&
Shell ont la même préséance contrairement à [[ || ]]
y [[ && ]]
y -o
, -a
y [
division des mots et génération de noms de fichiers lors des expansions (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 actuel.x='a b'; [ "$x" = 'a b' ]
: équivalent POSIX=
[[ ab = a? ]]
: vrai, parce que c'est le cas filtrage par motif ( * ? [
sont magiques). Ne développe pas les fichiers dans le répertoire courant.[ ab = a? ]
: a?
glob expanse. Donc peut être vrai ou faux selon les fichiers dans le répertoire courant.[ ab = a\? ]
: faux, pas d'expansion globale=
y ==
sont les mêmes dans les deux [
y [[
mais ==
est une extension de Bash.case ab in (a?) echo match; esac
: équivalent POSIX[[ ab =~ 'ab?' ]]
: false, perd la magie avec ''
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
)[[ ab? =~ 'ab?' ]]
: vrai=~
[[ ab =~ ab? ]]
: true, POSIX expression régulière étendue match, ?
n'est pas une extension globale[ a =~ a ]
: erreur de syntaxe. Pas d'équivalent en 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 [[ ]]
La construction que j'ai vue.
Si vous utilisez [[ ]]
vous :
[
est juste une commande normale avec un nom bizarre, aucune sémantique spéciale n'est impliquée.Merci à Stéphane Chazelas pour les corrections et ajouts importants.
@meeDamian if ( printf 'ab' | grep -Eq 'a' ); then echo 'a'; fi
. []
est une commande tout comme grep
. Le site ()
n'est peut-être pas nécessaire sur cette commande, je n'en suis pas sûr : je l'ai ajouté à cause de la |
ça dépend de la façon dont Bash analyse les choses. S'il n'y avait pas de |
Je suis sûr que vous pouvez écrire juste if cmd arg arg; then
.
Support unique c'est-à-dire []
est conforme à POSIX Shell pour enfermer une expression conditionnelle.
Supports doubles c'est-à-dire [[]]
est une version améliorée (ou extension) de la version POSIX standard, elle est prise en charge par bash et d'autres shells (zsh, ksh).
En bash, pour une comparaison numérique, on utilise eq
, ne
, lt
y gt
avec des doubles crochets pour la comparaison, nous pouvons utiliser ==
, !=
, <,
y >
littéralement.
[
est un synonyme de la commande test. Même si elle est intégrée au Shell, elle 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
SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.
4 votes
Au cas où vous vous demanderiez également s'il est possible de ne pas utiliser de parenthèses du tout, par exemple dans le contexte d'un fichier de type
if
déclaration, voir mywiki.wooledge.org/BashPitfalls#if_.5Bgrep_foo_myfile.5D0 votes
Également, à partir des docs d'Ubuntu : wiki.ubuntu.com/
1 votes
Voir aussi stackoverflow.com/questions/13542832/ , unix.stackexchange.com/questions/3831/
0 votes
Voir le lien sur Stack Overflow : opérateur unaire attendu