Question Quelle est la différence entre les crochets simples et doubles 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.


344
2017-08-09 21:11


origine


stackoverflow.com/questions/13542832 - Ciro Santilli 新疆改造中心 六四事件 法轮功
Au cas où vous vous demanderiez également de ne pas utiliser de crochets du tout, par ex. dans le contexte d'un if déclaration, voir mywiki.wooledge.org/BashPitfalls#if_.5Bgrep_foo_myfile.5D - Kev
aussi, à partir de la documentation Ubuntu: wiki.ubuntu.com/… - radistao


Réponses:


Il y a plusieurs différences. À mon avis, quelques-uns des plus importants sont:

  1. [ est un construit à Bash et de nombreux autres coquilles modernes. Le construit [ est similaire à test avec l'exigence supplémentaire d'une fermeture ]. Les construits [ et test imiter la fonctionnalité /bin/[ et /bin/test avec leurs limites afin que les scripts soient compatibles avec les versions antérieures. Les exécutables d'origine existent toujours principalement pour la conformité POSIX et la compatibilité ascendante. Exécuter la commande type [ dans Bash indique que [ est interprété comme un élément intégré par défaut. (Remarque: which [ ne cherche que les exécutables sur le CHEMIN et est équivalent à type -p [)
  2. [[ n'est pas aussi compatible, cela ne fonctionnera pas nécessairement avec /bin/sh pointe vers. Alors [[ est l'option plus moderne de Bash / Zsh / Ksh.
  3. Parce que [[ est intégré à la coque et n’a pas de configuration requise, vous n'avez pas à vous soucier de la séparation des mots en fonction de la IFS variable à gâcher sur les variables qui évaluent à une chaîne avec 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 difference entre test, [et [[?. En fait, si vous êtes sérieux au sujet des scripts bash, je vous recommande de lire l’ensemble du wiki, y compris la FAQ, Les piègeset guide. La section de test de la section de guide explique également ces différences et pourquoi les auteurs pensent [[ est un meilleur choix si vous n'avez pas à vous soucier d'être aussi portable. Les principales raisons sont:

  1. Vous n'avez pas à vous soucier de citer le côté gauche du test pour qu'il soit lu comme une variable.
  2. Vous n'avez pas à vous échapper moins que et plus grand que < > avec des barres obliques inverses afin de ne pas les évaluer en tant que redirection d’entrée, ce qui peut gâcher certaines choses en écrasant des fichiers. Cela remonte 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 > seulement si /bin/test est appelé, ce qui n'aurait pas vraiment de sens.

261
2017-08-09 21:56



Merci, le lien vers la FAQ de bash correspond à ce que je cherchais (je ne connaissais pas cette page, merci). - 0x89
J'ai édité votre message avec cette information, mais [et test sont exécutés comme des fonctions intégrées. Les commandes intégrées ont été conçues pour remplacer / bin / [et / bin / test, mais elles devaient également reproduire les limitations des fichiers binaires. La commande 'type [' vérifie que la commande intégrée est utilisée. 'qui [' recherche uniquement les exécutables sur le PATH et est équivalent à 'type -P [' - klynch


En bref:

[est une bash Intégré

[[]] 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.

La source: http://mywiki.wooledge.org/BashGuide/CommandsAndArguments


108
2017-12-29 19:42



[ est une commande shell POSIX; il n'a pas besoin d'être intégré. ] est juste un argument que cette commande recherche, pour que la syntaxe soit équilibrée. La commande est synonyme de test excepté test ne cherche pas de fermeture ]. - Kaz
Vois ici: pubs.opengroup.org/onlinepubs/009695399/utilities/test.html - Kaz


Différences de comportement

Testé dans Bash 4.3.11:

  • Extension POSIX vs Bash:

  • commande régulière vs magie

    • [ est juste une commande régulière avec un nom étrange.

      ] est juste un argument de [ qui empêche d’utiliser d’autres arguments.

      Ubuntu 16.04 a en réalité un exécutable pour cela à /usr/bin/[ fourni par coreutils, mais la version intégrée de bash a priorité.

      Rien ne change dans la manière dont Bash analyse la commande.

      En particulier, < est la redirection, && et || concaténer plusieurs commandes, ( ) génère des sous-coquilles à moins d'être échappé par \et l’extension du mot se passe comme d’habitude.

    • [[ X ]] est une construction unique qui fait X être analysé comme par magie. <, &&, || et () sont traités spécialement et les règles de fractionnement des mots sont différentes.

      Il y a aussi 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

  • <

  • && et ||

    • [[ a = a && b = b ]]: vrai, logique et
    • [ a = a && b = b ]: erreur de syntaxe, && analysé comme un séparateur de commandes AND cmd1 && cmd2 
    • [ a = a -a b = b ]: équivalent, mais obsolète par POSIX
    • [ a = a ] && [ b = b ]: Recommandation POSIX
  • (

    • [[ (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 ] Recommandation POSIX
  • fractionnement des mots

    • x='a b'; [[ $x = 'a b' ]]: true, les citations ne sont pas nécessaires
    • x='a b'; [ $x = 'a b' ]: erreur de syntaxe, passe à [ a b = 'a b' ]
    • x='a b'; [ "$x" = 'a b' ]: équivalent
  • =

    • [[ ab = a? ]]: vrai, parce que c'est le cas correspondance de modèle (* ? [ 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 selon les fichiers du répertoire en cours.
    • [ ab = a\? ]: false, pas l'expansion globale
    • = et == sont les mêmes dans les deux [ et [[, mais == est une extension de Bash.
    • printf 'ab' | grep -Eq 'a.': Équivalent POSIX ERE
    • [[ ab =~ 'ab?' ]]: faux, perd de la magie avec ''
    • [[ ab? =~ 'ab?' ]]: vrai
  • =~

    • [[ ab =~ ab? ]]: vrai, POSIX expression régulière étendue rencontre, ? ne se développe pas globalement
    • [ a =~ a ]: erreur de syntaxe
    • printf 'ab' | grep -Eq 'ab?': Équivalent POSIX

Recommandation

Je préfère toujours utiliser [].

Il existe des équivalents POSIX pour chaque [[ ]] construire j'ai vu.

Si tu utilises [[ ]] vous:

  • perdre la portabilité
  • forcer le lecteur à apprendre les subtilités d'une autre extension bash. [est juste une commande régulière avec un nom étrange, aucune sémantique particulière n’est impliquée.

61
2017-07-12 10:22



Comment utiliser printf 'ab' | grep -Eq 'ab?' dans if [ … ]? - meeDamian
@meeDamian if ( printf 'ab' | grep -Eq 'a' ); then echo 'a'; fi. [] est une commande comme grep. le () peut ne pas être nécessaire sur cette commande, je ne suis pas sûr: je l'ai ajouté à cause de la |, dépend de la façon dont Bash analyse les choses. S'il n'y avait pas | Je suis sûr que vous pouvez écrire juste if cmd arg arg; then. - Ciro Santilli 新疆改造中心 六四事件 法轮功
@meeDamian ouais, pas besoin de () il semble: stackoverflow.com/questions/8965509/… - Ciro Santilli 新疆改造中心 六四事件 法轮功
Belle liste! Voir également: wiki.ubuntu.com/… - radistao


Après une lecture rapide des sections pertinentes de la page de manuel, la principale différence semble être que le == et != opérateurs correspondent à un modèle, plutôt que d'une chaîne littérale, et aussi qu'il y a la =~ opérateur de comparaison de regex.


4
2017-08-09 21:17





Support unique c'est à dire. [] Le shell POSIX est-il compatible avec une expression conditionnelle?

Double crochets c'est à dire. [[]] est une version améliorée (ou une extension) de la version standard POSIX, elle est supportée par bash et d’autres shells (zsh, ksh).

En bash, pour la comparaison numérique, nous utilisons eq, ne,lt et gt, avec des doubles crochets pour la 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

3
2018-02-08 03:15