Réponses:
La différence entre [[ … ]]
et [ … ]
est principalement couverte par l’ utilisation de single - double brack - bash . De manière cruciale, la [[ … ]]
syntaxe spéciale, alors qu’il [
s’agit d’un nom amusant pour une commande. [[ … ]]
a des règles de syntaxe spéciales pour ce qui est à l'intérieur, [ … ]
n'a pas.
Avec la ride supplémentaire d'un caractère générique, voici comment [[ $a == z* ]]
est évalué:
[[ … ]]
construction conditionnelle autour de l’expression conditionnelle $a == z*
.==
opérateur binaire, avec les opérandes $a
et z*
.a
.==
opérateur: testez si la valeur de la variable a
correspond au modèle z*
.Voici comment [ $a == z* ]
est évalué:
[
commande avec les arguments formées en évaluant les mots $a
, ==
, z*
, ]
.$a
la valeur de la variable a
.a
est la chaîne de 6 caractères foo b*
(obtenue par exemple a='foo b*'
) et que la liste des fichiers du répertoire en cours est (bar
, baz
, qux
, zim
, zum
), le résultat de l'expansion est la liste suivante des mots: [
, foo
, bar
, baz
, ==
, zim
, zum
, ]
.[
avec les paramètres obtenus à l'étape précédente.
[
commande se plaint d'une erreur de syntaxe et renvoie le statut 2.Note: En venant du développement cité de ne correspond pas ). À l'intérieur , les guillemets doubles ne font pas de différence, sauf à droite des opérateurs de correspondance de chaîne.[[ $a == z* ]]
étape 3, la valeur de a
ne subit pas de fractionnement de mot ni de génération de nom de fichier, car elle se trouve dans un contexte dans lequel un seul mot est attendu (l'argument de gauche de l'opérateur conditionnel ==
). Dans la plupart des cas, si un seul mot a du sens à cette position, le développement variable se comporte comme entre guillemets. Il existe toutefois une exception à cette règle: in [[ abc == $a ]]
, si la valeur de a
contient des caractères génériques, elle a
correspond au modèle de caractère générique. Par exemple, si la valeur de a
is est a*
alors [[ abc == $a ]]
vraie (parce que le caractère générique *
provenant de l’extension non citée des $a
correspondances *
) alors qu’elle [[ abc == "$a" ]]
est fausse (parce que le caractère ordinaire*
$a
bc
[[ … ]]
( =
, ==
, !=
et =~
).
[
est un alias pour la test
commande. Unix version 6 avait une if
commande, mais la version 7 (1979) est venue avec le nouveau shell Bourne qui comportait quelques constructions de programmation, y compris la construction if-then-else-elif-fi, et Unix version 7 a ajouté untest
commande exécutant la plupart des opérations. "tests" réalisés par la if
commande dans les versions antérieures.
[
est devenu un alias test
et les deux ont été intégrés à la coque dans Unix System III (1981) . Il faut toutefois noter que certaines variantes d’Unix n’ont reçu de [
commande que bien plus tard ( jusqu’au début des années 2000, sur certains BSD, qui sh
est basé sur le shell Almquist.test
reçu de (une commande intégrée a toujours été incluse dans ash
le code source de BSDs il a été initialement désactivé)).
Notez que test
aka [
est une commande permettant d'effectuer des "tests". Aucune commande n'est effectuée par cette commande. Il n'y a donc aucune raison de dissocier les opérateurs d'affectation et d'égalité. L'opérateur d'égalité est donc =
.==
n’est supporté que par quelques implémentations récentes de [
(et n’est qu’un alias pour =
).
Parce [
qu’il n’ya rien de plus qu’une commande, elle est analysée de la même manière que toute autre commande du shell.
Dans votre exemple, $a
dans la mesure où il n’est pas cité, il serait divisé en plusieurs mots conformément aux règles habituelles de fractionnement des mots, et chaque mot subirait une génération de nom de fichier, appelée globbing, pour éventuellement aboutir à plus de mots, chacun de ces mots produisant un argument séparé à la [
commande.
De même, z*
serait élargi à la liste des noms de fichiers du répertoire actuel commençant par z
.
Ainsi , par exemple, si $a
est b* = x
, et il y a z1
, z2
, b1
et les b2
fichiers dans le répertoire courant, la [
commande obtiendraient 9 arguments: [
, b1
, b2
, =
, x
, ==
, z1
, z2
et]
.
[
analyse ses arguments en tant qu'expression conditionnelle. Ces 9 arguments ne correspondent pas à une expression conditionnelle valide, ce qui devrait donc renvoyer une erreur.
La [[ ... ]]
construction a été introduite par la coquille Korn probablement vers 1988, car ksh86a
en 1987, elle ne l’avait pas, elle l’ ksh88
avait depuis le début.
A côté de ksh (toutes les implémentations), [[...]]
est également supporté par bash (depuis la version 2.02) et zsh, mais les trois implémentations sont différentes et il existe des différences entre les versions d’un même shell, bien que les modifications soient généralement compatibles avec les versions antérieures (une exception notable étant la bash =~
opérateur connu pour casser quelques scripts après une certaine version lorsque son comportement a changé). [[...]]
n'est pas spécifié par POSIX, Unix ou Linux (LSB). Il a été envisagé d’être inclus à quelques reprises, mais n’est pas inclus car sa fonctionnalité commune prise en charge par les principaux shells est déjà couverte par la [
commande et la case-in-esac
construction.
Toute la [[ ... ]]
construction constitue une commande. C'est-à-dire qu'il a un statut de sortie (qui est son actif le plus important car il résulte de l'évaluation de l'expression conditionnelle), vous pouvez le diriger vers une autre commande (bien que cela ne soit pas utile), et l'utiliser généralement où vous le souhaitez. utilisez n'importe quelle autre commande (à l'intérieur du shell uniquement, car c'est une construction de shell) mais elle n'est pas analysée comme une commande simple normale. Ce qui est à l'intérieur est analysé par le shell comme une expression conditionnelle et les règles habituelles de fractionnement des mots et de génération de noms de fichiers s'appliquent différemment.
[[ ... ]]
est au courant ==
depuis le début et équivaut à =
1 . Une erreur de ksh est bien (et est source de confusion et de nombreux bugs) est que le =
et ==
ne sont pas un opérateur d'égalité , mais un opérateur de correspondance de motif (bien que le correspondant aspect peut être désactivé avec les guillemets mais avec des règles peu claires qui diffèrent de la coquille à coquille).
Dans votre code ci [[ $a == z* ]]
- dessus , le shell l’analyserait en plusieurs règles similaires aux règles habituelles, le reconnaîtrait comme une comparaison de correspondance de modèle, le traiterait z*
comme un modèle à faire correspondre au contenu dua
variable.
Généralement, il est plus difficile de se tirer dans le pied [[ ... ]]
qu'avec le [
commandement. Mais quelques règles comme
-a
ou -o
opérateur (utiliser plusieurs [
commandes et les &&
et ||
shell opérateurs)Rendre [
fiable avec les coques POSIX.
[[...]]
dans différents shells, prennent en charge des opérateurs supplémentaires tels que -nt
, les opérateurs de correspondance d'expressions rationnelles ... mais la liste et le comportement varient d'un shell à l'autre et d'une version à l'autre.
Donc, à moins que vous ne sachiez quel shell et quelle version minimum de votre script sera jamais interprété, il est probablement plus sûr de rester avec la [
commande standard .
1 Une exception: a [[...]]
été ajouté à bash dans la version 2.02
. Jusqu'à ce 2.03
que cela ait été changé, [[ x = '?' ]]
retournerait vrai et [[ x == '?' ]]
faux. Ce cite n'a pas empêché correspondance de motif lorsque vous utilisez l' =
opérateur dans ces versions, mais a fait lors de l' utilisation ==
.
[ '!' = foo -o a = a ]
de bash
par exemple.
les deux sont utilisés pour évaluer les expressions et [[ne fonctionnera pas avec POSIX, l’ancien shell bourn et [[prend également en charge les modèles de correspondance et les expressions rationnelles. exemple essayez ces
[ $n -eq 0 -a $y -eq 0 ] && echo "Error" || echo "Ok"
[[ $n -eq 0 && $y -eq 0 ]] && echo "Error" || echo "Ok"
[[...]]
prend en charge les expressions rationnelles que dans certaines versions de certains shells, tout comme certaines versions de [
support prennent en charge la correspondance des expressions rationnelles. Pour la comparaison arithmétique, dans ces coquilles qui supportent [[
, vous préférez écrire(( n == 0 && y == 0))