Pour autant que je sache, [[
est une version améliorée de [
, mais je suis confus quand je vois [[
un mot-clé et que je suis [
affiché comme un élément intégré.
[root@server ~]# type [
[ is a shell builtin
[root@server ~]# type [[
[[ is a shell keyword
TLDP dit
Une commande intégrée peut être un synonyme d'une commande système du même nom, mais Bash la réimplémente en interne. Par exemple, la commande Bash echo n’est pas la même chose que / bin / echo, bien que leur comportement soit presque identique.
et
Un mot clé est un mot, un jeton ou un opérateur réservé. Les mots clés ont une signification particulière pour le shell et sont en fait les éléments constitutifs de la syntaxe du shell. A titre d'exemple, pour, while, do, and! sont des mots-clés. Semblable à une commande intégrée, un mot-clé est codé en dur dans Bash, mais contrairement à une commande intégrée, un mot-clé n'est pas en soi une commande, mais une sous-unité d'une construction de commande. [2]
Cela ne devrait-il pas faire les deux [
et [[
un mot clé? Y a-t-il quelque chose qui me manque ici? En outre, ce lien réaffirme que les deux [
et [[
doivent appartenir au même genre.
la source
if "[" $x -eq 3 ]
fonctionne comme prévu (parce que Bash cherche la commande appelée[
, et cela existe), maisif "[[" $x -eq 3 ]]
ne fonctionne pas (car encore une fois, Bash cherche une commande du nom approprié, mais il n’existe pas[[
commander)./usr/bin/echo
, mais cela ne signifie pas pour autant que ce n'est pas intégré .Réponses:
La différence entre
[
et[[
est assez fondamentale.[
est une commande. Ses arguments sont traités exactement comme les autres arguments de commandes. Par exemple, considérons:Le shell développera
$name
et effectuera le fractionnement des mots et la génération du nom de fichier sur le résultat, comme pour toute autre commande.À titre d'exemple, les éléments suivants vont échouer:
Pour que cela fonctionne correctement, des guillemets sont nécessaires:
[[
est un mot clé shell et ses arguments sont traités selon des règles spéciales. Par exemple, considérons:Le shell se développera
$name
mais, contrairement à toute autre commande, il ne réalisera ni fractionnement de mot, ni génération de nom de fichier sur le résultat. Par exemple, ce qui suit réussira malgré les espaces incorporés dansname
:Sommaire
[
est une commande et est soumise aux mêmes règles que toutes les autres commandes exécutées par le shell.Parce que
[[
c'est un mot-clé, pas une commande, cependant, le shell le traite spécialement et il fonctionne selon des règles très différentes.la source
man bash
. Voir, en particulier, les sections "EXTENSION DE COMMANDE SIMPLE" et "EXÉCUTION DE COMMANDE". En plus[[
, d' autres bash mots - clés comprennentif
,then
,while
et « cas ». Il n'y a pas de règles générales pour les mots-clés: chaque mot-clé constitue un cas particulier.man bash
comprend des détails pour chacun.Dans la V7, Unix - où le shell Bourne a fait ses débuts -
[
était appelétest
et il n'existait que/bin/test
. Donc, le code que vous écririez aujourd'hui comme:vous auriez écrit à la place
Cette deuxième notation existe toujours, et j'estime qu'elle est plus claire à propos de ce qui se passe: vous appelez une commande appelée
test
, qui évalue ses arguments et renvoie un code de statut de sortie qui permetif
de décider quoi faire ensuite. Cette commande peut être intégrée au shell ou être un programme externe¹.[
comme alternative à plustest
tard. Il s’agit peut-être d’un synonyme intégrétest
, mais il est également fourni comme/bin/[
sur les systèmes modernes pour les réservoirs qui ne l’ont pas intégré.[
ettest
peut être mis en œuvre en utilisant le même code. C’est le cas pour/bin/[
et/bin/test
sur OS X, où ce sont des liens physiques vers le même exécutable.³ En conséquence, l’implémentation ignore complètement la fin]
: elle ne l’exige pas si vous l’appelez comme/bin/[
, et elle ne se plaint pas si vous le fournissez à/bin/test
.⁴Aucune de cette histoire n'affecte
[[
, car il n'y a jamais eu de programme primordial appelé[[
. Il existe uniquement à l'intérieur des shells qui l'implémentent comme une extension du shell POSIX .Une partie de la distinction entre "builtin" et "keyword" est due à cette histoire. Cela reflète également le fait que les règles de syntaxe pour l'analyse d'
[[
expressions sont différentes, comme indiqué dans la réponse de John1024.Notes de bas de page:
Lorsque vous le considérez de cette façon, vous comprenez pourquoi vous devez placer des espaces
[
dans les scripts shell, contrairement à la façon dont les parenthèses et les crochets fonctionnent dans la plupart des autres langages de programmation. Si l'analyseur de commandes du shell le permettaitif["$x"...
, il devrait également permettreiftest"$x"...
C’est arrivé vers 1980.
/bin/[
n’existe pas dans mon exemplaire d’ Ancient Unix V7 de 1979, niman test
dans un alias. Dans l'entrée de page de manuel correspondante je dans une préversion du système III manuel de 1980, il est répertorié.ls -i /bin/[ /bin/test
Mais ne comptez pas sur ce comportement. La Bash la version intégrée de
[
nécessite la fermeture]
, et son intégré latest
mise en œuvre se plaindra si vous ne fournissez.La distinction commande interne + commande externe peut également être importante pour une autre raison: les deux implémentations peuvent se comporter différemment. C'est le cas
echo
sur de nombreux systèmes. Comme il n'y a qu'une seule implémentation, aucune distinction de ce type n'est nécessaire pour un mot clé.la source
builtin
etkeyword
distinction entre[
et[[
lorsque les deux fournit la même fonctionnalité ( à l' exception du fait que[[
vient avec plus de fonctionnalités que[
)?[[
étant un mot clé permet à bash de faire des choses qui ne sont pas possibles[
- par exemple, la citation n'est pas nécessaire beaucoup de temps, car le shell sait qu'il s'agit d'une variable. Autrement dit, le traitement de la ligne de commande est affecté lorsqu'un mot-clé est utilisé, mais pas lorsqu'une commande intégrée est utilisée - cela se produit beaucoup plus tard.[
intégrée, mais que le code est mis en commentaire.cd
est une fonction intégrée, mais elle n’observe rien (cd
ne peut pas être implémentée en tant que programme externe).[[
un mot clé permet au shell d’utiliser des règles d’analyse syntaxiques spéciales. Ainsi, hélas, mon vote positif va à John1024.[
était à l'origine juste une commande externe, un autre nom pour/bin/test
. Mais quelques commandes, telles que[
etecho
, sont utilisées si souvent dans les scripts shell que les développeurs de celui-ci ont décidé de copier le code directement dans le shell, plutôt que de devoir exécuter un autre processus à chaque utilisation. Cela a transformé ces commandes en "commandes intégrées", bien que vous puissiez toujours appeler le programme externe via son chemin complet.[[
est venu beaucoup plus tard. Bien que la commande intégrée soit implémentée en interne dans le shell, elle est analysée comme une commande externe. Comme expliqué dans la réponse de John1024, cela signifie que les variables non citées subiront un fractionnement des mots, ainsi que des jetons similaires à>
et<
seront traitées comme une redirection d'E / S. Cela rendait difficile l’écriture d’expressions de comparaison complexes.[[
a été créé en tant que syntaxe de shell, afin de pouvoir être analysé idéosyncratiquement. Les[[
variables internes ne comportent pas de fractionnement des mots<
et>
peuvent être utilisées en tant qu'opérateurs de comparaison=
. Elles peuvent se comporter différemment selon que le paramètre suivant est cité ou non, etc. Toutes ces commodités sont[[
plus faciles à utiliser que les[
commandes / fonctions intégrées traditionnelles .Ils ne pourraient pas simplement recoder une
[
syntaxe comme celle-ci car cela aurait été une modification incompatible à des millions de scripts. En utilisant la nouvelle[[
syntaxe, qui n'existait pas auparavant, ils pourraient totalement réorganiser la manière dont elle est utilisée de manière compatible.Ceci est similaire à l'évolution qui a abouti à la
$((...))
syntaxe des expressions arithmétiques, qui a principalement remplacé laexpr
commande traditionnelle .la source
Le plus récent
[[
enbash
est une optimisation de[
.Le classique
[
a un gros inconvénient, quand il est fréquemment utilisé pour effectuer une opération triviale: ilgénère à chaque fois un nouveau processus: (Il crée un nouvel espace adresse juste pour comparer
0
et1
! À chaque fois!)Je pense que l’un des principaux objectifs de l’ajout de
[[
était de faire en sorte que l’évaluation de l’expression à l’intérieur[
ne génère pas un processus supplémentaire. Mais comment cela[
fonctionne ne pourrait pas être changé - cela créerait beaucoup de confusion et de problèmes. Ainsi, l'optimisation a été mise en œuvre avec un nouveau nom, de manière plus efficace, à savoir une commande intégrée au shell.Il est devenu mot clé dans la syntaxe du shell en tant qu'effet secondaire.
À l’époque
[
, c’était la bonne façon de procéder avec un processus externe.la source
[
origine d’une commande externe, elle a été ajoutée assez tôt au shell, probablement au moment de la sortie de Unix System III et certainement avant celle de Unix System V. Le processus supplémentaire n'a donc pas été un problème depuis des lustres. Cependant, la syntaxe est restée inchangée - elle a été traitée comme s'il s'agissait d'une commande externe.[
soit à la fois - cela signifie quelques changements ...