Je suis un peu confus sur ce que ces opérateurs font différemment lorsqu'ils sont utilisés en bash (crochets, doubles crochets, parenthèses et doubles parenthèses).
[[ , [ , ( , ((
J'ai vu des gens les utiliser si, comme ceci:
if [[condition]]
if [condition]
if ((condition))
if (condition)
Réponses:
Une
if
déclaration ressemble généralement àLa
then
clause est exécutée si le code de sortiecommands1
est zéro. Si le code de sortie est différent de zéro, laelse
clause est exécutée.commands1
peut être simple ou complexe. Il peut, par exemple, être une séquence d'un ou plusieurs pipelines séparés par l' un des opérateurs;
,&
,&&
, ou||
. Lesif
conditions ci-dessous ne sont que des cas particuliers decommands1
:if [ condition ]
C'est la
test
commande shell traditionnelle . Il est disponible sur tous les shells POSIX. La commande de test définit un code de sortie et l'if
instruction agit en conséquence. Les tests typiques sont si un fichier existe ou si un nombre est égal à un autre.if [[ condition ]]
Il s'agit d'une nouvelle version mise à niveau
test
de ksh que bash et zsh prennent également en charge. Cettetest
commande définit également un code de sortie et l'if
instruction agit en conséquence. Parmi ses fonctionnalités étendues, il peut tester si une chaîne correspond à une expression régulière.if ((condition))
Une autre extension ksh que bash et zsh supportent également. Ceci effectue une arithmétique. À la suite de l'arithmétique, un code de sortie est défini et l'
if
instruction agit en conséquence. Il renvoie un code de sortie de zéro (vrai) si le résultat du calcul arithmétique est différent de zéro. Comme[[...]]
, cette forme n'est pas POSIX et donc pas portable.if (command)
Ceci exécute la commande dans un sous-shell. Lorsque la commande est terminée, elle définit un code de sortie et l'
if
instruction agit en conséquence.Une raison typique pour l' utilisation d' un sous - shell comme celui - ci est de limiter les effets secondaires de
command
si lescommand
affectations de variables nécessaires ou d' autres changements dans l'environnement de la coquille. De tels changements ne restent pas une fois le sous-shell terminé.if command
La commande est exécutée et l'
if
instruction agit en fonction de son code de sortie.la source
[
s'agit en fait d'un fichier binaire, et non d'une commande ou d'un symbole interne. Habite généralement à/bin
.[
est en fait un construit, tel queltest
. Des versions binaires sont disponibles pour des raisons de compatibilité. Départhelp [
ethelp test
.$((
c'est -à- dire que le développement de l'arithmétique est facile et il est facile de les confondre. Souvent, une solution de contournement consiste à utiliser quelque chose comme l'[ $((2+2)) -eq 4 ]
utilisation de l'arithmétique dans des déclarations conditinales(…)
les parenthèses indiquent un sous - shell . Ce qu’ils contiennent n’est pas une expression comme dans beaucoup d’autres langues. C'est une liste de commandes (tout comme entre parenthèses). Ces commandes étant exécutées dans un sous-processus distinct, toute redirection, affectation, etc. effectuée à l'intérieur des parenthèses n'a aucun effet en dehors des parenthèses.$(…)
y a substitution de commande : il y a une commande à l'intérieur des parenthèses et le résultat de la commande est utilisé dans le cadre de la ligne de commande (après des extensions supplémentaires, à moins que la substitution ne soit entre guillemets, mais c'est une autre histoire ) .{ … }
Les accolades ressemblent aux parenthèses dans le sens où elles regroupent des commandes, mais elles n'influencent que l'analyse, pas le regroupement. Le programmex=2; { x=4; }; echo $x
imprime 4, alors que lesx=2; (x=4); echo $x
impressions 2. (Les accolades étant des mots-clés doivent également être délimitées et trouvées en position de commande (d'où les espaces après{
et;
avant}
) alors que les parenthèses ne le sont pas. C'est juste un problème de syntaxe.)${VAR}
est une extension de paramètre , élargissant la valeur d’une variable, avec des transformations supplémentaires possibles. Leksh93
shell supporte également${ cmd;}
comme forme de substitution de commande qui ne génère pas de sous-shell.((…))
les doubles parenthèses entourent une instruction arithmétique , c'est-à-dire un calcul sur des entiers, avec une syntaxe ressemblant à d'autres langages de programmation. Cette syntaxe est principalement utilisée pour les affectations et dans les conditions. Cela n'existe que dans ksh / bash / zsh, pas en clair sh.$((…))
, qui se développent à la valeur entière de l'expression.[ … ]
les parenthèses simples entourent les expressions conditionnelles . Les expressions conditionnelles sont principalement construites sur des opérateurs, par exemple-n "$variable"
pour vérifier si une variable est vide et-e "$file"
pour vérifier si un fichier existe. Notez que vous avez besoin d'un espace autour de chaque opérateur (par exemple[ "$x" = "$y" ]
, non) et d'un espace ou d'un caractère identique[ "$x"="$y" ]
;
à l'intérieur et à l'extérieur des crochets (par exemple[ -n "$foo" ]
, non).[-n "$foo"]
[[ … ]]
les doubles crochets sont une forme alternative d'expressions conditionnelles dans ksh / bash / zsh avec quelques fonctionnalités supplémentaires, par exemple, vous pouvez écrire[[ -L $file && -f $file ]]
pour tester si un fichier est un lien symbolique vers un fichier normal, alors que des crochets simples l'exigent[ -L "$file" ] && [ -f "$file" ]
. Voir Pourquoi le développement de paramètres avec des espaces sans guillemets fonctionne-t-il entre doubles crochets [[mais pas entre crochets [? pour plus sur ce sujet.Dans le shell, chaque commande est une commande conditionnelle: chaque commande a un état de retour égal à 0, indiquant un succès ou un entier compris entre 1 et 255 (et potentiellement davantage dans certains interpréteurs) indiquant un échec. La
[ … ]
commande (ou[[ … ]]
forme syntaxique) est une commande particulière qui peut également être épeléetest …
et réussit lorsqu'un fichier existe, ou lorsqu'une chaîne n'est pas vide, ou lorsqu'un nombre est inférieur à un autre, etc. La((…))
forme syntaxique réussit lorsqu'un nombre est non nul. Voici quelques exemples de conditions dans un script shell:Testez si
myfile
contient la chaînehello
:Si
mydir
est un répertoire, changez-le et faites les choses suivantes:Testez s'il y a un fichier appelé
myfile
dans le répertoire en cours:Les mêmes, mais incluant également des liens symboliques pendants:
Teste si la valeur de
x
(supposée numérique) est d'au moins 2, de manière portable:Teste si la valeur de
x
(supposée numérique) est d'au moins 2, en bash / ksh / zsh:la source
-a
lieu de&&
, on peut donc écrire:[ -L $file -a -f $file ]
qui est le même nombre de caractères dans les supports sans supplément[
et]
...-a
et-o
sont problématiques car ils peuvent conduire à des analyses syntaxiques incorrectes si certains des opérandes impliqués ressemblent à des opérateurs. C'est pourquoi je ne les mentionne pas: ils n'ont aucun avantage et ne fonctionnent pas toujours. Et n’écrivez jamais d’extensions de variables non entre guillemets sans raison valable:[[ -L $file -a -f $file ]]
c’est bien, mais vous avez besoin de crochets simples[ -L "$file" -a -f "$file" ]
(ce qui est correct, par exemple si$file
commence toujours par/
ou./
).[[ -L $file && -f $file ]]
(non-a
avec la[[...]]
variante).De la documentation bash :
En d'autres termes, vous vous assurez que tout ce qui se passe dans 'list' (comme a
cd
) n'a aucun effet en dehors de(
et)
. La seule chose qui fuite est le code de sortie de la dernière commande ou avecset -e
la première commande qui génère une erreur (autre que quelques tels queif
,while
, etc.)Ceci est une extension bash vous permettant de faire des maths. Ceci est un peu similaire à l'utilisation
expr
sans toutes les limitations deexpr
(comme avoir des espaces partout, s'échapper*
, etc.)Ceci offre un test avancé permettant de comparer des chaînes, des nombres et des fichiers un peu comme des
test
offres, mais plus puissants.Celui-ci appelle
test
. En fait, jadis,[
était un lien symbolique verstest
. Cela fonctionne de la même manière et vous avez les mêmes limites. Puisqu’un binaire connaît le nom avec lequel il a été démarré, le programme de test peut analyser les paramètres jusqu’à ce qu’il trouve un paramètre]
. Des trucs amusants sous Unix.Notez que dans le cas de
bash
,[
ettest
sont des fonctions intégrées (comme mentionné dans un commentaire), les mêmes limitations s'appliquent à peu près.la source
test
et[
soient bien sûr des commandes intégrées à Bash, il est probable qu’un binaire externe existe aussi.[
n'est pas un lien symboliquetest
sur la plupart des systèmes modernes.strings /usr/bin/test
montre en fait qu'il a aussi le texte d'aide, alors je ne sais pas quoi dire.test
commande doive manifestement exister sous forme de commande autonome basée sur un fichier selon la norme, rien n’indique que sa[
variante doit également être implémentée de cette façon. Par exemple, Solaris 11 ne fournit aucun[
fichier exécutable, mais est néanmoins totalement conforme aux normes POSIX[
contre[[
Cette réponse couvrira le sous-ensemble
[
vs[[
de la question.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
oub
(comme+
ouindex
) et effectue une comparaison numérique sia
etb
ressemble à des entiers décimaux.expr "x$a" '<' "x$b"
travaille autour des deux.³ et échoue également pour certaines valeurs de
a
oub
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.la source
expr
à la réponse. Le terme "extension Bash" ne veut pas dire que Bash a été le premier shell à ajouter une syntaxe. Apprendre POSIX sh vs Bash est déjà suffisant pour me rendre fou.man test
si vous avez essayéman [
et vous êtes perdu. Cela expliquera la variante POSIX.Quelques exemples:
Test traditionnel:
test
et[
sont des commandes comme les autres, donc la variable est divisée en mots, sauf si elle est entre guillemets.Test de nouveau style
[[ ... ]]
est une construction shell spéciale (plus récente), qui fonctionne un peu différemment, la chose la plus évidente étant qu'elle ne divise pas les variables en mots:Un peu de documentation sur
[
et[[
ici .Test arithmétique:
Commandes "normales":
Tout ce qui précède agit comme une commande normale et
if
peut prendre n’importe quelle commande:Commandes multiples:
Ou nous pouvons utiliser plusieurs commandes. Envelopper un ensemble de commandes dans les
( ... )
exécute dans le sous-shell, créant une copie temporaire de l'état du shell (répertoire de travail, variables). Si nous devons exécuter un programme temporairement dans un autre répertoire:la source
Commandes de regroupement
( list )
Le fait de placer une liste de commandes entre parenthèses entraîne la création d’un environnement de sous-shell et l’exécution de chacune des commandes de la liste dans ce sous-shell. Comme la liste est exécutée dans un sous-shell, les affectations de variables ne restent pas en vigueur une fois le sous-shell terminé.{ list; }
Si vous placez une liste de commandes entre des accolades, la liste sera exécutée dans le contexte actuel du shell . Aucun sous-shell n'est créé. La liste suivante en point-virgule (ou nouvelle ligne) est requise. La sourceConstructions conditionnelles
Support simple à savoir A
[]
titre de comparaison
==, !=, <,
et>
et doivent être utilisés et pour la comparaison numériqueeq, ne,lt
etgt
doit être utilisé.Supports améliorés ie
[[]]
Dans tous les exemples ci-dessus, nous n’utilisons que des crochets simples pour entourer l’expression conditionnelle, mais bash autorise les doubles crochets, qui servent de version améliorée de la syntaxe à crochet unique.
Pour comparaison
==, !=, <,
et>
peut utiliser 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.[[
est compris parKorn
etBash
.La source
la source