Par exemple, la commande suivante ne fonctionne pas:
if [[-e xyz]]; then echo File exists;fi
ksh donne l'erreur suivante
[[-e: command not found
Est-ce parce que "[[-" "est ambigu?
command-line
syntax
ksh
AcBap
la source
la source
[[
est un mot - clé - vraisemblablement l'arbre d'analyse du shell nécessite que les mots-clés soient délimités par des espacesRéponses:
L'explication la plus simple serait, car dans le manuel, elle apparaît comme
[[ expression ]]
telle qu'il doit y avoir un espace entre[[
etexpression
et la fermeture]]
. Mais bien sûr, nous pouvons essayer de l'examiner plus en profondeur. Les coquilles ont une grammaire quelque peu complexe et reposent fortement sur le concept de "division de mots". En particulier, le manuel ksh (1) indique:Ainsi, comme indiqué dans le manuel, la séquence de caractères
[[-e
est considérée comme un mot shell.ksh
rechercherait une telle commande dans la liste des opérateurs intégrés et spéciaux (commefor
ouwhile
), puis rechercherait une commande externe - et voilà - aucune trouvée, donc il y a un message d'erreur sur la commande introuvable.Dans ce cas, ce
[[
ne sont pas non plus des méta-caractères spéciaux. S'ils l'étaient, la-e
partie en[[-e
serait considérée comme un mot shell, et non comme un argument en[[
soi. Cependant, elle[[
est décrite comme une commande composée et le manuel dit ce qui suit:Ainsi, pour
[[
être reconnu comme une commande composée, il doit s'agir du premier mot d'une commande ou d'une liste de commandes, ce qui, selon la définition précédente d'un "mot", implique qu'il doit être séparé par des espaces, des tabulations ou des nouvelles lignes des autres mots / arguments.Vous avez demandé dans les commentaires : "Pourquoi l'analyseur ne peut-il pas s'arrêter dès qu'il trouve" [["modèle, et le traite comme le début d'une commande conditionnelle?" La réponse courte est probablement parce que 1) l'influence de la
[
syntaxe, car il s'agissait à l'origine d'une commande externe, et pour la norme POSIX, la conformité existe encore aujourd'hui en tant que commande externe, et 2) parce que l'analyseur shell est construit de cette manière. L'analyseur de shell peut reconnaître d'autres caractères spéciaux non délimités par l'espace:echo $((2+2))
et(echo foobar)
fonctionne parfaitement bien. Peut-être qu'à l'avenir, lorsque leksh
développement reprendra ou qu'il semble y avoir un fork ou un clone (commemksh
oupdksh
), quelqu'un implémentera la syntaxe sans espace dans[[-e
.Voir également:
[[
est appelé un "mot réservé" (voir la section 2.9 du langage de commande Shell ). Par définition POSIX, le mot réservé doit être délimité par des espaces. En revanche,(
est un opérateur, et la norme indique dans la section 2.9 "les représentations incluent l'espacement entre les jetons à certains endroits où<blank>
s ne serait pas nécessaire (lorsque l'un des jetons est un opérateur)". Voir la discussion connexe: Grammaire POSIX Shell: pourquoi Brace Group a besoin du premier espace alors que Subshell n'en a pas?la source
char
est un mot-clé mais vous ne pouvez toujours pas écrirecharsomeletter = 'A';
et vous attendre à ce que l'analyseur s'arrête après avoir vuchar
.i--<=++j
, et le compilateur n'a aucun problème à analyser cela commei -- <= ++ j
._
). Ksh a(
comme opérateur et(echo hello)
analyse comme( echo hello )
. Il aif
,{
,[[
et d' autres mots - clés , etifx
,{x
et[[x
sont chacun un jeton - comme la façon dontcharsomeletter
est l' un jeton C. En revanche, un non cité(x
dans ksh est deux jetons - commei--
c'est le cas pour deux jetons en C. Ce que cela signifie même conceptuellement d'être un opérateur diffère entre les coquilles de style Bourne (comme ksh) et C. réelle similitude lexicale .Ce qui est important à noter, c'est qu'il
[
s'agit d'une commande, et le mot clé shell[[
dans bash et ksh est basé sur[
.[[
est utilisé de manière similaire à[
. Parfois , vous pouvez même remplacer[
]
avec[[
]]
sans changement de comportement. Avec[
, comme toute commande, un espace est obligatoire entre la commande et ses arguments. La même chose s'applique à[[
.Nous en avions seulement
/usr/bin/[
. Maintenant, la plupart des shells sont[
intégrés pour plus d'efficacité, mais la syntaxe est la même. Dans les coquilles qui le fournissent[[
, il fonctionne comme une alternative plus polyvalente à[
.Voici la description de
[
in bash:[
Est donc équivalent àtest
(à part attendre un]
argument à la toute fin).help test
donnera encore plus de détails à ce sujet. Vous pouvez comparer cela àhelp [[
.Il existe également une page de manuel pour la commande externe
[
(man \[
).Dans le cas de
[
pas non plus de[[
commande, là. Le mot complet[[-e
est.if [[-e
fait un test vrai / faux. Existe-t-il donc une commande[[-e
?Oui. Ou pas.
[[-e
est ce que c'est: rien que le shell comprenne donc il suppose que c'est sa propre commande. ;-)la source
[[-e
est un nom de commande potentiellement valide (si bizarre).L'espace est un délimiteur et est requis. Comme vous pouvez le voir sur
shellcheck
:(Les deux ksh et bash prennent en charge
[[
et ne fonctionnent pas sans l'espace. Shellcheck donne exactement cette sortie avec des scripts ksh et bash similaires contenant cette ligne de bogue.)La raison pour laquelle les suppresseurs sont nécessaires est liée aux jetons et aux lexiques .
la source
ksh
shell dans la question. Bash emprunte l'[[
opérateur àksh
et dans cette question, leur comportement est identique, mais je serais prudent avec les hypothèses car il y a des différences significatives entreksh
et lebash
comportement et les internes. C'est juste parce que shellcheck fonctionne sur le script bash, ce n'est peut-être pas nécessairement l'outil approprié pour les scripts ksh. Juste quelque chose à garder à l'esprit lors de l'approche de différents obus[[
règles intégrées. Je n'imaginais nullement qu'ilksh
s'agissait d'un obus dans lequel ilshellcheck
pouvait trouver des erreurs. J'espère que d'autres apprécientksh
etbash
sont deux interprètes différents. Merci d'avoir mentionné cela. Il convient également de noter[[
un bash intégré alors qu'il[
s'agit d'une commande externe.[
c'est aussi un bash intégré :) manpages.ubuntu.com/manpages/bionic/man7/bash-builtins.7.html Mais vous n'êtes pas loin -[
outest
vous devez être une commande externe. Au temps du Bourne shell d'origine[
était en fait une commande externe, et existe toujours de nos jours/usr/bin/[
car POSIX exige qu'il s'agisse d'une commande externe pubs.opengroup.org/onlinepubs/009695399/utilities/test.html Très peu sont requis par POSIX pour être intégré pubs.opengroup.org/onlinepubs/009695399/idx/sbi.html L'intégration[
est pour l'efficacitéksh
; utilisez un hashbang ou-s ksh
. Btw, ksh et bash ont[[
"intégré", mais c'est un mot - clé , contrairement[
, qui est un shell intégré . (ksh :;whence -v [ [[
bashtype [ [[
:) Les commandes internes et externes sont syntaxiquement similaires. Une façon[[
diffère de[
celle qui[[
supprime certaines extensions dans ses arguments, ce qu'elle ne pourrait pas en tant que module intégré - tout comme{
le regroupement ne pouvait pas être un module intégré. C'est peut-être pourquoi{x
(ou[[x
) être un jeton semble étrange. Je pense qu'il est juste de dire que les commandes internes et les mots clés sont lexicalement mais pas syntaxiquement similaires. @SergiyKolodyazhnyy[[
peut être une commande externe! Autrement dit, il peut s'agir d'un programme et non d'une syntaxe directement prise en charge par votre shell. La prise en charge d'une syntaxe sans espace serait possible,ksh
mais elle échouerait sur les systèmes avec externe,[[
donc pour des raisons de compatibilité, il est préférable de conserver l'espace requis.BusyBox fournit par
[[
exemple une commande externe .la source
Depuis
[[-e
peut participer à l'expansion du shell (il peut être utilisé commeafin de répertorier tous les fichiers commençant par une lettre entre
[
ete
inclusivement), ce serait un gâchis complet si[
et si]
des caractères spéciaux ne participaient pas à la division normale des mots régie par des espaces.la source