Nous avons effectué des expériences pour étudier la grammaire des scripts batch. Nous avons également étudié les différences entre les modes batch et ligne de commande.
Analyseur de ligne par lots:
Voici un bref aperçu des phases de l'analyseur de ligne de fichier de commandes:
Phase 0) Lire la ligne:
Phase 1) Pourcentage d'expansion:
Phase 2) Traiter les caractères spéciaux, tokenize et créer un bloc de commande mis en cache: il s'agit d'un processus complexe qui est affecté par des éléments tels que les guillemets, les caractères spéciaux, les délimiteurs de jetons et les échappements d'insertion.
Phase 3) Faire écho à la ou aux commandes analysées Uniquement si le bloc de commande n'a pas commencé par @
, et ECHO était ON au début de l'étape précédente.
Phase 4) Extension de %X
variable FOR : Uniquement si une commande FOR est active et que les commandes après DO sont en cours de traitement.
Phase 5) Expansion retardée: uniquement si l'expansion retardée est activée
Phase 5.3) Traitement des tuyaux: Uniquement si les commandes se trouvent de chaque côté d'un tuyau
Phase 5.5) Exécuter la redirection:
Phase 6) Traitement CALL / Doublage du curseur: Uniquement si le jeton de commande est CALL
Phase 7) Exécuter: la commande est exécutée
Voici les détails de chaque phase:
Notez que les phases décrites ci-dessous ne sont qu'un modèle du fonctionnement de l'analyseur par lots. Les composants internes réels de cmd.exe peuvent ne pas refléter ces phases. Mais ce modèle est efficace pour prédire le comportement des scripts batch.
Phase 0) Lire la ligne: Lisez d'abord la ligne d'entrée <LF>
.
- Lors de la lecture d'une ligne à analyser en tant que commande,
<Ctrl-Z>
(0x1A) est lu comme <LF>
(LineFeed 0x0A)
- Lorsque GOTO ou CALL lit des lignes tout en recherchant un: label
<Ctrl-Z>
,, est traité comme lui-même - il n'est pas converti en<LF>
Phase 1) Pourcentage d'expansion:
- Un double
%%
est remplacé par un simple%
- Expansion des arguments (
%*
, %1
, %2
, etc.)
- Expansion de
%var%
, si var n'existe pas, remplacez-la par rien
- La ligne est tronquée au début,
<LF>
pas dans l' %var%
expansion
- Pour une explication complète, lisez la première moitié de ceci sur dbenham Même fil: Phase de pourcentage
Phase 2) Traiter les caractères spéciaux, tokenize et créer un bloc de commande mis en cache: il s'agit d'un processus complexe qui est affecté par des éléments tels que les guillemets, les caractères spéciaux, les délimiteurs de jetons et les échappements d'insertion. Ce qui suit est une approximation de ce processus.
Certains concepts sont importants tout au long de cette phase.
- Un jeton est simplement une chaîne de caractères qui est traitée comme une unité.
- Les jetons sont séparés par des délimiteurs de jetons. Les délimiteurs de jetons standard sont
<space>
<tab>
;
,
=
<0x0B>
<0x0C>
et <0xFF>
Les délimiteurs de jetons consécutifs sont traités comme un seul - il n'y a pas de jetons vides entre les délimiteurs de jetons
- Il n'y a pas de délimiteurs de jeton dans une chaîne entre guillemets. La chaîne entière entre guillemets est toujours traitée comme faisant partie d'un seul jeton. Un seul jeton peut être constitué d'une combinaison de chaînes entre guillemets et de caractères non entre guillemets.
Les caractères suivants peuvent avoir une signification particulière dans cette phase, selon le contexte: <CR>
^
(
@
&
|
<
>
<LF>
<space>
<tab>
;
,
=
<0x0B>
<0x0C>
<0xFF>
Regardez chaque caractère de gauche à droite:
- Si
<CR>
alors supprimez-le, comme s'il n'était jamais là (sauf pour un comportement de redirection étrange )
- Si un signe d'insertion (
^
), le caractère suivant est échappé et le signe d'insertion d'échappement est supprimé. Les caractères échappés perdent toute signification spéciale (sauf pour <LF>
).
- S'il s'agit d'un guillemet (
"
), activez l'indicateur de citation. Si l'indicateur de devis est actif, alors seulement "
et <LF>
sont spéciaux. Tous les autres caractères perdent leur signification spéciale jusqu'à ce que la citation suivante désactive l'indicateur de citation. Il n'est pas possible d'échapper au devis de clôture. Tous les caractères entre guillemets sont toujours dans le même jeton.
<LF>
désactive toujours l'indicateur de citation. D'autres comportements varient selon le contexte, mais les citations ne modifient jamais le comportement de <LF>
.
- Échappé
<LF>
<LF>
est dépouillé
- Le caractère suivant est échappé. Si à la fin du tampon de ligne, alors la ligne suivante est lue et traitée par les phases 1 et 1.5 et ajoutée à la ligne courante avant d'échapper au caractère suivant. Si le caractère suivant est
<LF>
, il est traité comme un littéral, ce qui signifie que ce processus n'est pas récursif.
- Sans échappement
<LF>
pas entre parenthèses
<LF>
est supprimé et l'analyse de la ligne actuelle est terminée.
- Tous les caractères restants dans le tampon de ligne sont simplement ignorés.
- Sans échappement
<LF>
dans un bloc entre parenthèses FOR IN
<LF>
est converti en un <space>
- Si à la fin du tampon de ligne, la ligne suivante est lue et ajoutée à la ligne courante.
- Sans échappement
<LF>
dans un bloc de commande entre parenthèses
<LF>
est converti en <LF><space>
, et le <space>
est traité comme faisant partie de la ligne suivante du bloc de commande.
- Si à la fin du tampon de ligne, la ligne suivante est lue et ajoutée à l'espace.
- Si l'un des caractères spéciaux
&
|
<
ou >
, divisez la ligne à ce stade afin de gérer les tubes, la concaténation des commandes et la redirection.
- Dans le cas d'un tube (
|
), chaque côté est une commande séparée (ou bloc de commandes) qui reçoit un traitement spécial dans la phase 5.3
- Dans le cas de
&
, &&
ou de ||
concaténation de commandes, chaque côté de la concaténation est traité comme une commande distincte.
- Dans le cas de
<
, <<
, >
ou la >>
redirection, la clause de redirection est analysé, retiré temporairement, puis ajouté à la fin de la commande en cours. Une clause de redirection se compose d'un chiffre de descripteur de fichier facultatif, de l'opérateur de redirection et du jeton de destination de redirection.
- Si le jeton qui précède l'opérateur de redirection est un seul chiffre non échappé, le chiffre spécifie le descripteur de fichier à rediriger. Si le jeton de poignée n'est pas trouvé, la redirection de sortie prend par défaut la valeur 1 (stdout) et la redirection d'entrée par défaut sur 0 (stdin).
- Si le tout premier jeton pour cette commande (avant de déplacer la redirection vers la fin) commence par
@
, alors le @
a une signification particulière. ( @
n'est pas spécial dans aucun autre contexte)
- Le spécial
@
est supprimé.
- Si ECHO est activé, cette commande, ainsi que toutes les commandes concaténées suivantes sur cette ligne, sont exclues de l'écho de phase 3. Si le
@
est avant une ouverture (
, alors le bloc entier entre parenthèses est exclu de l'écho de phase 3.
- Traiter les parenthèses (fournit des instructions composées sur plusieurs lignes):
- Si l'analyseur ne recherche pas de jeton de commande, ce
(
n'est pas spécial.
- Si l'analyseur recherche un jeton de commande et le trouve
(
, démarrez une nouvelle instruction composée et incrémentez le compteur de parenthèses
- Si le compteur de parenthèses est> 0, alors
)
termine l'instruction composée et décrémente le compteur de parenthèses.
- Si la fin de la ligne est atteinte et que le compteur de parenthèses est> 0, la ligne suivante sera ajoutée à l'instruction composée (recommence avec la phase 0)
- Si le compteur de parenthèses est égal à 0 et que l'analyseur recherche une commande, alors
)
fonctionne comme une REM
instruction tant qu'elle est immédiatement suivie d'un délimiteur de jeton, d'un caractère spécial, d'une nouvelle ligne ou d'une fin de fichier
- Tous les caractères spéciaux perdent leur signification sauf
^
(la concaténation des lignes est possible)
- Une fois que la fin de la ligne logique est atteinte, la "commande" entière est rejetée.
- Chaque commande est analysée en une série de jetons. Le premier jeton est toujours traité comme un jeton de commande (après que les spéciaux
@
ont été supprimés et la redirection déplacée vers la fin).
- Les délimiteurs de jeton avant le jeton de commande sont supprimés
- Lors de l'analyse du jeton de commande,
(
fonctionne comme un délimiteur de jeton de commande, en plus des délimiteurs de jeton standard
- La gestion des jetons suivants dépend de la commande.
- La plupart des commandes concaténent simplement tous les arguments après le jeton de commande en un seul jeton d'argument. Tous les délimiteurs de jeton d'argument sont conservés. Les options d'argument ne sont généralement pas analysées avant la phase 7.
- Trois commandes bénéficient d'un traitement spécial - IF, FOR et REM
- IF est divisé en deux ou trois parties distinctes qui sont traitées indépendamment. Une erreur de syntaxe dans la construction IF entraînera une erreur de syntaxe fatale.
- L'opération de comparaison est la commande réelle qui passe tout au long de la phase 7
- Toutes les options IF sont entièrement analysées en phase 2.
- Les délimiteurs de jetons consécutifs se réduisent en un seul espace.
- En fonction de l'opérateur de comparaison, il y aura un ou deux jetons de valeur qui seront identifiés.
- Le bloc de commande True est l'ensemble des commandes après la condition et est analysé comme n'importe quel autre bloc de commande. Si ELSE doit être utilisé, le bloc True doit être entre parenthèses.
- Le bloc de commande optionnel False est l'ensemble des commandes après ELSE. Encore une fois, ce bloc de commande est analysé normalement.
- Les blocs de commande Vrai et Faux ne sont pas automatiquement transférés dans les phases suivantes. Leur traitement ultérieur est contrôlé par la phase 7.
- FOR est divisé en deux après le DO. Une erreur de syntaxe dans la construction FOR entraînera une erreur de syntaxe fatale.
- La partie passant par DO est la commande d'itération FOR réelle qui traverse la phase 7
- Toutes les options FOR sont entièrement analysées en phase 2.
- La clause entre parenthèses IN est traitée
<LF>
comme <space>
. Une fois la clause IN analysée, tous les jetons sont concaténés pour former un seul jeton.
- Les délimiteurs de jetons consécutifs sans échappement / sans guillemets se réduisent en un seul espace tout au long de la commande FOR via DO.
- La partie après DO est un bloc de commande qui est analysé normalement. Le traitement ultérieur du bloc de commande DO est contrôlé par l'itération de la phase 7.
- Le REM détecté en phase 2 est traité de manière radicalement différente de toutes les autres commandes.
- Un seul jeton d'argument est analysé - l'analyseur ignore les caractères après le premier jeton d'argument.
- La commande REM peut apparaître dans la sortie de la phase 3, mais la commande n'est jamais exécutée et le texte de l'argument d'origine est renvoyé - les carets d'échappement ne sont pas supprimés, sauf ...
- S'il n'y a qu'un seul jeton d'argument qui se termine par un jeton sans échappement
^
qui termine la ligne, le jeton d'argument est jeté et la ligne suivante est analysée et ajoutée au REM. Cela se répète jusqu'à ce qu'il y ait plus d'un jeton, ou que le dernier caractère ne soit pas ^
.
- Si le jeton de commande commence par
:
, et que c'est le premier tour de la phase 2 (pas un redémarrage dû à CALL en phase 6), alors
- Le jeton est normalement traité comme une étiquette non exécutée .
- Mais le reste de la ligne est analysée,
)
, <
, >
, &
et |
ne plus avoir une signification particulière. Tout le reste de la ligne est considéré comme faisant partie de l'étiquette «commande».
- Le
^
continue d'être spécial, ce qui signifie que la continuation de ligne peut être utilisée pour ajouter la ligne suivante à l'étiquette.
- Une étiquette non exécutée dans un bloc entre parenthèses entraînera une erreur de syntaxe fatale à moins qu'elle ne soit immédiatement suivie d'une commande ou d'une étiquette exécutée sur la ligne suivante.
(
n'a plus de signification particulière pour la première commande qui suit l' étiquette non exécutée .
- La commande est abandonnée une fois l'analyse des étiquettes terminée. Les phases suivantes n'ont pas lieu pour le label
- Il existe trois exceptions qui peuvent entraîner le traitement d'une étiquette trouvée dans la phase 2 comme une étiquette exécutée qui continue l'analyse jusqu'à la phase 7.
- Il y a redirection qui précède l'étiquette jeton, et il y a un
|
tuyau ou &
, &&
ou ||
concaténation de commande sur la ligne.
- Il y a une redirection qui précède le jeton d'étiquette et la commande se trouve dans un bloc entre parenthèses.
- Le jeton d'étiquette est la toute première commande sur une ligne dans un bloc entre parenthèses, et la ligne ci-dessus se termine par une étiquette non exécutée .
- Ce qui suit se produit lorsqu'une étiquette exécutée est découverte dans la phase 2
- L'étiquette, ses arguments et sa redirection sont tous exclus de toute sortie d'écho en phase 3
- Toutes les commandes concaténées ultérieures sur la ligne sont entièrement analysées et exécutées.
- Pour plus d' informations sur les étiquettes Exécuté par rapport aux étiquettes non exécutés , voir https://www.dostips.com/forum/viewtopic.php?f=3&t=3803&p=55405#p55405
Phase 3) Faire écho à la ou aux commandes analysées Uniquement si le bloc de commande n'a pas commencé par @
, et ECHO était ON au début de l'étape précédente.
Phase 4) Extension de %X
variable FOR : Uniquement si une commande FOR est active et que les commandes après DO sont en cours de traitement.
- À ce stade, la phase 1 du traitement par lots aura déjà converti une variable FOR comme
%%X
en %X
. La ligne de commande a des règles d'expansion de pourcentage différentes pour la phase 1. C'est la raison pour laquelle les lignes de commande utilisent %X
mais les fichiers de commandes utilisent %%X
pour les variables FOR.
- Les noms de variables FOR sont sensibles à la casse, mais
~modifiers
ne le sont pas.
~modifiers
ont la priorité sur les noms de variables. Si un caractère suivant ~
est à la fois un modificateur et un nom de variable FOR valide et qu'il existe un caractère suivant qui est un nom de variable FOR actif, le caractère est interprété comme un modificateur.
- Les noms de variables FOR sont globaux, mais uniquement dans le contexte d'une clause DO. Si une routine est CALLed à partir d'une clause FOR DO, les variables FOR ne sont pas développées dans la routine CALLed. Mais si la routine a sa propre commande FOR, alors toutes les variables FOR actuellement définies sont accessibles aux commandes DO internes.
- Les noms de variables FOR peuvent être réutilisés dans des FOR imbriqués. La valeur FOR interne est prioritaire, mais une fois que INNER FOR se ferme, la valeur FOR externe est restaurée.
- Si ECHO était sur ON au début de cette phase, alors la phase 3) est répétée pour afficher les commandes DO analysées une fois que les variables FOR ont été développées.
---- A partir de ce moment, chaque commande identifiée en phase 2 est traitée séparément.
---- Les phases 5 à 7 sont terminées pour une commande avant de passer à la suivante.
Phase 5) Expansion retardée: Uniquement si l'expansion retardée est activée, la commande n'est pas dans un bloc entre parenthèses de chaque côté d'un tube , et la commande n'est pas un script batch "nu" (nom du script sans parenthèses, CALL, concaténation de commandes, ou tuyau).
- Chaque jeton d'une commande est analysé indépendamment pour une expansion retardée.
- La plupart des commandes analysent deux jetons ou plus: le jeton de commande, le jeton d'arguments et chaque jeton de destination de redirection.
- La commande FOR analyse uniquement le jeton de clause IN.
- La commande IF analyse uniquement les valeurs de comparaison - une ou deux, selon l'opérateur de comparaison.
- Pour chaque jeton analysé, vérifiez d'abord s'il en contient
!
. Sinon, le jeton n'est pas analysé - ce qui est important pour les ^
caractères. Si le jeton contient !
, scannez chaque caractère de gauche à droite:
- S'il s'agit d'un signe d'insertion (
^
), le caractère suivant n'a pas de signification particulière, le signe d'insertion lui-même est supprimé
- S'il s'agit d'un point d'exclamation, recherchez le point d'exclamation suivant (les carets ne sont plus observés), développez jusqu'à la valeur de la variable.
- Les ouvertures consécutives
!
sont regroupées en une seule!
- Tout élément non apparié restant
!
est supprimé
- L'expansion des variables à ce stade est "sûre", car les caractères spéciaux ne sont plus détectés (même
<CR>
ou <LF>
)
- Pour une explication plus complète, lisez la deuxième moitié de ce fil de discussion sur dbenham
même - Phase d'exclamation
Phase 5.3) Traitement des tuyaux: Uniquement si les commandes sont de chaque côté d'un tuyau.
Chaque côté du tuyau est traité indépendamment et de manière asynchrone.
- Si la commande est interne à cmd.exe, ou s'il s'agit d'un fichier de commandes, ou s'il s'agit d'un bloc de commande entre parenthèses, elle est exécutée dans un nouveau thread cmd.exe via
%comspec% /S /D /c" commandBlock"
, de sorte que le bloc de commande obtient un redémarrage de phase, mais cette fois en mode ligne de commande.
- Si un bloc de commande entre parenthèses, alors tous
<LF>
avec une commande avant et après sont convertis en <space>&
. D'autres <LF>
sont dépouillés.
- C'est la fin du traitement des commandes pipe.
- Voir Pourquoi l'expansion retardée échoue-t-elle à l'intérieur d'un bloc de code canalisé? pour en savoir plus sur l'analyse et le traitement des tuyaux
Phase 5.5) Exécuter la redirection: Toute redirection découverte dans la phase 2 est maintenant exécutée.
Phase 6) Traitement de l'APPEL / Doublage du curseur: Uniquement si le jeton de commande est CALL, ou si le texte avant le premier délimiteur de jeton standard survenant est CALL. Si CALL est analysé à partir d'un jeton de commande plus grand, la partie inutilisée est ajoutée au jeton d'arguments avant de continuer.
- Scannez le jeton d'arguments pour un
/?
. S'il se trouve n'importe où dans les jetons, abandonnez la phase 6 et passez à la phase 7, où l'AIDE pour l'APPEL sera imprimée.
- Retirez le premier
CALL
, afin que plusieurs appels puissent être empilés
- Double tous les carets
- Redémarrez les phases 1, 1.5 et 2, mais ne passez pas à la phase 3
- Tous les caractères doublés sont ramenés à un caret tant qu'ils ne sont pas cités. Mais malheureusement, les carets cités restent doublés.
- La phase 1 change un peu
- Les erreurs d'expansion à l'étape 1.2 ou 1.3 annulent l'APPEL, mais l'erreur n'est pas fatale - le traitement par lots se poursuit.
- Les tâches de la phase 2 sont un peu modifiées
- Toute nouvelle redirection non entre guillemets et sans échappement qui n'a pas été détectée au premier tour de la phase 2 est détectée, mais elle est supprimée (y compris le nom de fichier) sans effectuer réellement la redirection
- Tout signe d'insertion non entre guillemets et sans échappement nouvellement apparu à la fin de la ligne est supprimé sans effectuer de continuation de ligne
- L'appel est interrompu sans erreur si l'un des éléments suivants est détecté
- Apparaissant récemment non cité, non échappé
&
ou|
- Le jeton de commande résultant commence par sans guillemets, sans échappement
(
- Le tout premier jeton après l'appel supprimé a commencé par
@
- Si la commande résultante est un IF ou FOR apparemment valide, l'exécution échouera par la suite avec une erreur indiquant que
IF
ouFOR
n'est pas reconnue comme une commande interne ou externe.
- Bien sûr, l'APPEL n'est pas abandonné dans ce 2ème tour de la phase 2 si le jeton de commande résultant est une étiquette commençant par
:
.
- Si le jeton de commande résultant est CALL, redémarrez la phase 6 (se répète jusqu'à ce qu'il n'y ait plus d'appels)
- Si le jeton de commande résultant est un script batch ou une étiquette:, l'exécution de l'APPEL est entièrement gérée par le reste de la phase 6.
- Poussez la position actuelle du fichier de script de commandes sur la pile d'appels afin que l'exécution puisse reprendre à partir de la position correcte lorsque l'APPEL est terminé.
- Configurez les jetons d'argument% 0,% 1,% 2, ...% N et% * pour l'APPEL, en utilisant tous les jetons résultants
- Si le jeton de commande est une étiquette commençant par
:
, alors
- Redémarrez la phase 5. Cela peut avoir un impact sur ce que: l'étiquette est appelée. Mais comme les jetons% 0 etc. ont déjà été configurés, cela ne modifiera pas les arguments qui sont passés à la routine CALLed.
- Exécutez l'étiquette GOTO pour positionner le pointeur de fichier au début du sous-programme (ignorez tous les autres jetons qui peuvent suivre l'étiquette:) Voir la phase 7 pour les règles sur le fonctionnement de GOTO.
- Sinon, transférez le contrôle au script batch spécifié.
- L'exécution de l'étiquette ou du script CALLed: continue jusqu'à ce que EXIT / B ou la fin du fichier soit atteint, à quel point la pile CALL est sautée et l'exécution reprend à partir de la position du fichier enregistré.
La phase 7 n'est pas exécutée pour les scripts CALLed ou: labels.
- Sinon, le résultat de la phase 6 passe à la phase 7 pour exécution.
Phase 7) Exécuter: la commande est exécutée
- 7.1 - Exécuter la commande interne - Si le jeton de commande est cité, alors sautez cette étape. Sinon, essayez d'analyser une commande interne et de l'exécuter.
- Les tests suivants sont effectués pour déterminer si un jeton de commande sans guillemets représente une commande interne:
- Si le jeton de commande correspond exactement à une commande interne, exécutez-la.
- Sinon casser le jeton de commande avant la première occurrence de
+
/
[
]
<space>
<tab>
,
;
ou =
Si le texte précédent est une commande interne, alors rappelez-vous cette commande
- Si en mode ligne de commande, ou si la commande provient d'un bloc entre parenthèses, si un bloc de commande vrai ou faux, un bloc de commande FOR DO ou si elle est impliquée dans la concaténation de commandes, exécutez la commande interne
- Sinon (doit être une commande autonome en mode de traitement par lots) scannez le dossier actuel et le PATH pour un fichier .COM, .EXE, .BAT ou .CMD dont le nom de base correspond au jeton de commande d'origine
- Si le premier fichier correspondant est un .BAT ou .CMD, allez à 7.3.exec et exécutez ce script
- Sinon (correspondance non trouvée ou première correspondance .EXE ou .COM) exécutez la commande interne mémorisée
- Sinon coupez le jeton de commande avant la première occurrence de
.
\
ou :
Si le texte précédent n'est pas une commande interne, allez à 7.2
Sinon, le texte précédent peut être une commande interne. Souvenez-vous de cette commande.
- Casser le jeton de commande avant la première occurrence de
+
/
[
]
<space>
<tab>
,
;
ou =
Si le texte précédent est un chemin vers un fichier existant, allez à 7.2
Sinon exécutez la commande interne mémorisée.
- Si une commande interne est analysée à partir d'un jeton de commande plus grand, la partie inutilisée du jeton de commande est incluse dans la liste d'arguments
- Ce n'est pas parce qu'un jeton de commande est analysé comme une commande interne qu'il s'exécutera avec succès. Chaque commande interne a ses propres règles quant à la façon dont les arguments et les options sont analysés et la syntaxe autorisée.
- Toutes les commandes internes afficheront l'aide au lieu d'exécuter leur fonction si elle
/?
est détectée. La plupart reconnaissent /?
s'il apparaît n'importe où dans les arguments. Mais quelques commandes comme ECHO et SET n'impriment de l'aide que si le premier jeton d'argument commence par /?
.
- SET a une sémantique intéressante:
- Si une commande SET a un guillemet avant que le nom de la variable et les extensions ne soient activés
set "name=content" ignored
-> valeur = content
alors le texte entre le premier signe égal et le dernier guillemet est utilisé comme contenu (premier égal et dernier guillemet exclus). Le texte après le dernier guillemet est ignoré. S'il n'y a pas de guillemet après le signe égal, le reste de la ligne est utilisé comme contenu.
- Si une commande SET n'a pas de guillemet avant le nom
set name="content" not ignored
-> valeur = "content" not ignored
alors tout le reste de la ligne après l'égal est utilisé comme contenu, y compris tous les guillemets qui peuvent être présents.
- Une comparaison IF est évaluée et, selon que la condition est vraie ou fausse, le bloc de commande dépendant déjà analysé approprié est traité, en commençant par la phase 5.
- La clause IN d'une commande FOR est itérée de manière appropriée.
- S'il s'agit d'un FOR / F qui itère la sortie d'un bloc de commande, alors:
- La clause IN est exécutée dans un nouveau processus cmd.exe via CMD / C.
- Le bloc de commande doit passer par l'ensemble du processus d'analyse une deuxième fois, mais cette fois dans un contexte de ligne de commande
- ECHO démarrera sur ON et l'expansion différée commencera généralement désactivée (en fonction du paramètre de registre)
- Toutes les modifications d'environnement effectuées par le bloc de commande de la clause IN seront perdues une fois le processus cmd.exe enfant terminé
- Pour chaque itération:
- Les valeurs de la variable FOR sont définies
- Le bloc de commande DO déjà analysé est ensuite traité en commençant par la phase 4.
- GOTO utilise la logique suivante pour localiser le: label
- L'étiquette est analysée à partir du premier jeton d'argument
- Le script est analysé pour la prochaine occurrence de l'étiquette
- L'analyse commence à partir de la position actuelle du fichier
- Si la fin du fichier est atteinte, l'analyse revient au début du fichier et continue au point de départ d'origine.
- L'analyse s'arrête à la première occurrence de l'étiquette trouvée et le pointeur de fichier est défini sur la ligne qui suit immédiatement l'étiquette. L'exécution du script reprend à partir de ce point. Notez qu'un vrai GOTO réussi annulera immédiatement tout bloc de code analysé, y compris les boucles FOR.
- Si l'étiquette n'est pas trouvée ou si le jeton d'étiquette est manquant, alors le GOTO échoue, un message d'erreur est imprimé et la pile d'appels s'affiche. Cela fonctionne effectivement comme un EXIT / B, sauf que toutes les commandes déjà analysées dans le bloc de commande actuel qui suivent le GOTO sont toujours exécutées, mais dans le contexte du CALLer (le contexte qui existe après EXIT / B)
- Voir https://www.dostips.com/forum/viewtopic.php?f=3&t=3803 pour une description plus précise des règles utilisées pour l'analyse des étiquettes.
- RENAME et COPY acceptent tous les deux des caractères génériques pour les chemins source et cible. Mais Microsoft fait un travail terrible en documentant le fonctionnement des caractères génériques, en particulier pour le chemin cible. Un ensemble utile de règles génériques peut être trouvé dans Comment la commande Windows RENAME interprète-t-elle les caractères génériques?
- 7.2 - Exécuter le changement de volume - Sinon, si le jeton de commande ne commence pas par un guillemet, fait exactement deux caractères et le 2ème caractère est un deux-points, changez le volume
- Tous les jetons d'argument sont ignorés
- Si le volume spécifié par le premier caractère est introuvable, abandonnez avec une erreur
- Un jeton de commande de
::
entraînera toujours une erreur à moins que SUBST ne soit utilisé pour définir un volume pour ::
Si SUBST est utilisé pour définir un volume pour ::
, alors le volume sera modifié, il ne sera pas traité comme une étiquette.
- 7.3 - Exécuter une commande externe - Sinon, essayez de traiter la commande comme une commande externe.
- Si en mode ligne de commande et la commande n'est pas cité et ne commence pas par une spécification de volume, l' espace blanc,
,
, ;
,=
ou +
alors casser la commande jeton à la première occurrence <space>
,
;
ou =
et préfixer le reste à l'argument jeton (s).
- Si le deuxième caractère du jeton de commande est un signe deux-points, vérifiez que le volume spécifié par le premier caractère peut être trouvé.
Si le volume est introuvable, abandonnez avec une erreur.
- Si en mode batch et que le jeton de commande commence par
:
, alors allez à 7.4
Notez que si le jeton d'étiquette commence par ::
, alors cela ne sera pas atteint car l'étape précédente aura abandonné avec une erreur à moins que SUBST ne soit utilisé pour définir un volume pour ::
.
- Identifiez la commande externe à exécuter.
- Il s'agit d'un processus complexe qui peut impliquer le volume actuel, le répertoire actuel, la variable PATH, la variable PATHEXT et / ou les associations de fichiers.
- Si une commande externe valide ne peut pas être identifiée, abandonnez avec une erreur.
- Si en mode ligne de commande et que le jeton de commande commence par
:
, alors allez à 7.4
Notez que cela est rarement atteint car l'étape précédente aura été abandonnée avec une erreur à moins que le jeton de commande ne commence par::
, et SUBST est utilisé pour définir un volume pour ::
, et le le jeton de commande entier est un chemin valide vers une commande externe.
- 7.3.exec - Exécute la commande externe.
- 7.4 - Ignorer une étiquette - Ignorer la commande et tous ses arguments si le jeton de commande commence par
:
.
Les règles en 7.2 et 7.3 peuvent empêcher une étiquette d'atteindre ce point.
Analyseur de ligne de commande:
Fonctionne comme le BatchLine-Parser, sauf:
Phase 1) Pourcentage d'expansion:
- Non
%*
,%1
etc. extension d'argument
- Si var n'est pas défini, alors
%var%
est laissé inchangé.
- Aucune manipulation particulière de
%%
. Si var = content, alors%%var%%
développe en%content%
.
Phase 3) Faire écho à la ou aux commandes analysées
- Ceci n'est pas effectué après la phase 2. Il n'est effectué qu'après la phase 4 pour le bloc de commande FOR DO.
Phase 5) Expansion retardée: uniquement si DelayedExpansion est activée
- Si var n'est pas défini, alors
!var!
est laissé inchangé.
Phase 7) Exécuter la commande
- Les tentatives de CALL ou GOTO a: label génèrent une erreur.
- Comme déjà documenté dans la phase 7, une étiquette exécutée peut entraîner une erreur dans différents scénarios.
- Les étiquettes exécutées par lots ne peuvent provoquer une erreur que si elles commencent par
::
- Les étiquettes exécutées en ligne de commande entraînent presque toujours une erreur
Analyse des valeurs entières
Il existe de nombreux contextes différents dans lesquels cmd.exe analyse les valeurs entières des chaînes et les règles sont incohérentes:
SET /A
IF
%var:~n,m%
(expansion de sous-chaîne variable)
FOR /F "TOKENS=n"
FOR /F "SKIP=n"
FOR /L %%A in (n1 n2 n3)
EXIT [/B] n
Les détails de ces règles peuvent être trouvés dans Règles pour la manière dont CMD.EXE analyse les nombres
Pour toute personne souhaitant améliorer les règles d'analyse cmd.exe, il existe un sujet de discussion sur le forum DosTips où les problèmes peuvent être signalés et des suggestions.
J'espère que cela aide
Jan Erik (jeb) - Auteur original et découvreur de phases
Dave Benham (dbenham) - Beaucoup de contenu et d'édition supplémentaires