Je suis tombé sur ss64.com qui fournit une bonne aide sur la façon d'écrire des scripts batch que l'interpréteur de commandes Windows exécutera.
Cependant, je n'ai pas pu trouver une bonne explication de la grammaire des scripts batch, comment les choses se développent ou ne s'étendent pas, et comment échapper aux choses.
Voici des exemples de questions que je n'ai pas pu résoudre:
- Comment le système de devis est-il géré? J'ai créé un script TinyPerl
(foreach $i (@ARGV) { print '*' . $i ; }
), je l'ai compilé et je l'ai appelé ainsi:my_script.exe "a ""b"" c"
→ la sortie est*a "b*c
my_script.exe """a b c"""
→ le sortir*"a*b*c"
- Comment fonctionne la
echo
commande interne ? Qu'est-ce qui est développé dans cette commande? - Pourquoi dois-je utiliser
for [...] %%I
dans des scripts de fichiers, maisfor [...] %I
dans des sessions interactives? - Quels sont les personnages d'échappement et dans quel contexte? Comment échapper à un signe de pourcentage? Par exemple, comment puis-je faire écho
%PROCESSOR_ARCHITECTURE%
littéralement? J'ai trouvé que çaecho.exe %""PROCESSOR_ARCHITECTURE%
marche, y a-t-il une meilleure solution? - Comment les paires de
%
match? Exemple:set b=a
,echo %a %b% c%
→%a a c%
set a =b
,echo %a %b% c%
→bb c%
- Comment puis-je m'assurer qu'une variable passe à une commande en tant qu'argument unique si jamais cette variable contient des guillemets doubles?
- Comment les variables sont-elles stockées lors de l'utilisation de la
set
commande? Par exemple, si je faisset a=a" b
et alorsecho.%a%
j'obtiensa" b
. Si j'utilise cependantecho.exe
des UnxUtils, j'obtiensa b
. Comment se%a%
développe-t-il d'une manière différente?
Merci pour tes lumières.
Réponses:
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>
.<Ctrl-Z>
(0x1A) est lu comme<LF>
(LineFeed 0x0A)<Ctrl-Z>
,, est traité comme lui-même - il n'est pas converti en<LF>
Phase 1) Pourcentage d'expansion:
%%
est remplacé par un simple%
%*
,%1
,%2
, etc.)%var%
, si var n'existe pas, remplacez-la par rien<LF>
pas dans l'%var%
expansionPhase 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.
<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
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:
<CR>
alors supprimez-le, comme s'il n'était jamais là (sauf pour un comportement de redirection étrange )^
), 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>
)."
), 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>
.<LF>
<LF>
est dépouillé<LF>
, il est traité comme un littéral, ce qui signifie que ce processus n'est pas récursif.<LF>
pas entre parenthèses<LF>
est supprimé et l'analyse de la ligne actuelle est terminée.<LF>
dans un bloc entre parenthèses FOR IN<LF>
est converti en un<space>
<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.&
|
<
ou>
, divisez la ligne à ce stade afin de gérer les tubes, la concaténation des commandes et la redirection.|
), 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&
,&&
ou de||
concaténation de commandes, chaque côté de la concaténation est traité comme une commande distincte.<
,<<
,>
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.@
, alors le@
a une signification particulière. (@
n'est pas spécial dans aucun autre contexte)@
est supprimé.@
est avant une ouverture(
, alors le bloc entier entre parenthèses est exclu de l'écho de phase 3.(
n'est pas spécial.(
, démarrez une nouvelle instruction composée et incrémentez le compteur de parenthèses)
termine l'instruction composée et décrémente le compteur de parenthèses.)
fonctionne comme uneREM
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^
(la concaténation des lignes est possible)@
ont été supprimés et la redirection déplacée vers la fin).(
fonctionne comme un délimiteur de jeton de commande, en plus des délimiteurs de jeton standard<LF>
comme<space>
. Une fois la clause IN analysée, tous les jetons sont concaténés pour former un seul jeton.^
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^
.:
, et que c'est le premier tour de la phase 2 (pas un redémarrage dû à CALL en phase 6), alors)
,<
,>
,&
et|
ne plus avoir une signification particulière. Tout le reste de la ligne est considéré comme faisant partie de l'étiquette «commande».^
continue d'être spécial, ce qui signifie que la continuation de ligne peut être utilisée pour ajouter la ligne suivante à l'étiquette.(
n'a plus de signification particulière pour la première commande qui suit l' étiquette non exécutée .|
tuyau ou&
,&&
ou||
concaténation de commande sur la ligne.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.%%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.~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.---- 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).
!
. 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:^
), le caractère suivant n'a pas de signification particulière, le signe d'insertion lui-même est supprimé!
sont regroupées en une seule!
!
est supprimé<CR>
ou<LF>
)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.
%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.<LF>
avec une commande avant et après sont convertis en<space>&
. D'autres<LF>
sont dépouillés.Phase 5.5) Exécuter la redirection: Toute redirection découverte dans la phase 2 est maintenant exécutée.
||
est utilisé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.
/?
. 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.CALL
, afin que plusieurs appels puissent être empilés&
ou|
(
@
IF
ouFOR
n'est pas reconnue comme une commande interne ou externe.:
.:
, alorsLa phase 7 n'est pas exécutée pour les scripts CALLed ou: labels.
Phase 7) Exécuter: la commande est exécutée
+
/
[
]
<space>
<tab>
,
;
ou=
Si le texte précédent est une commande interne, alors rappelez-vous cette commande
.
\
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.
+
/
[
]
<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.
/?
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 "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.
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.
::
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.,
,;
,=
ou+
alors casser la commande jeton à la première occurrence<space>
,
;
ou=
et préfixer le reste à l'argument jeton (s).Si le volume est introuvable, abandonnez avec une erreur.
:
, alors allez à 7.4Notez 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::
.:
, alors allez à 7.4Notez 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.:
.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:
%*
,%1
etc. extension d'argument%var%
est laissé inchangé.%%
. Si var = content, alors%%var%%
développe en%content%
.Phase 3) Faire écho à la ou aux commandes analysées
Phase 5) Expansion retardée: uniquement si DelayedExpansion est activée
!var!
est laissé inchangé.Phase 7) Exécuter la commande
::
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
la source
)
fonctionne vraiment presque comme uneREM
commande lorsque le compteur de parenthèses est 0. Essayez les deux à partir de la ligne de commande) Ignore this
echo OK & ) Ignore this
Lors de l'appel d'une commande à partir d'une fenêtre de commande, la tokenisation des arguments de la ligne de commande n'est pas effectuée par
cmd.exe
(alias "le shell"). Le plus souvent, la tokenisation est effectuée par le runtime C / C ++ des processus nouvellement formés, mais ce n'est pas nécessairement le cas - par exemple, si le nouveau processus n'a pas été écrit en C / C ++, ou si le nouveau processus choisit d'ignorerargv
et de traiter la ligne de commande brute pour elle-même (par exemple avec GetCommandLine () ). Au niveau du système d'exploitation, Windows transmet les lignes de commande non validées sous forme de chaîne unique aux nouveaux processus. Cela contraste avec la plupart des shells * nix, où le shell tokenise les arguments de manière cohérente et prévisible avant de les transmettre au processus nouvellement formé. Tout cela signifie que vous pouvez rencontrer des comportements de tokenisation des arguments extrêmement divergents entre différents programmes sous Windows, car les programmes individuels prennent souvent en main la tokenisation des arguments.Si cela ressemble à de l'anarchie, c'est en quelque sorte. Cependant, étant donné qu'un grand nombre de programmes Windows n'utiliser le moteur d' exécution Microsoft C / C ++ de , il peut être généralement utile de comprendre comment le MSVCRT tokenizes arguments. Voici un extrait:
argv
Le "langage par lots" de Microsoft (
.bat
) ne fait pas exception à cet environnement anarchique, et il a développé ses propres règles uniques pour la tokenisation et l'échappement. Il semble également que l'invite de commande de cmd.exe effectue un prétraitement de l'argument de ligne de commande (principalement pour la substitution de variable et l'échappement) avant de transmettre l'argument au processus qui vient d'être exécuté. Vous pouvez en savoir plus sur les détails de bas niveau du langage batch et de l'échappement de cmd dans les excellentes réponses de jeb et dbenham sur cette page.Construisons un simple utilitaire de ligne de commande en C et voyons ce qu'il dit à propos de vos cas de test:
(Remarques: argv [0] est toujours le nom de l'exécutable, et est omis ci-dessous par souci de concision. Testé sur Windows XP SP3. Compilé avec Visual Studio 2005.)
Et quelques-uns de mes propres tests:
la source
[a "b" c]
pourrait devenir[a "b] [c]
le post-traitement.GetCommandLine
. Peut-être que TinyPerl ignore argv et symbolise simplement la ligne de commande brute selon ses propres règles.Règles d'expansion en pourcentage
Voici une explication détaillée de la phase 1 dans la réponse de jeb (valable pour le mode batch et le mode ligne de commande).
Phase 1) Pourcentage d'expansion En commençant par la gauche, scannez chaque caractère pour
%
ou<LF>
. Si trouvé alors<LF>
)<LF>
alors<LF>
partir de<CR>
)%
, alors passez à 1.1%
) ignoré si le mode ligne de commande%
puisremplacer
%%
avec un seul%
et de poursuivre l' analyse*
et les extensions de commande sont activées,remplacez
%*
par le texte de tous les arguments de ligne de commande (remplacez par rien s'il n'y a pas d'arguments) et poursuivez l'analyse.<digit>
thenRemplacez
%<digit>
par la valeur de l'argument (remplacez par rien si non défini) et poursuivez l'analyse.~
et les extensions de commande sont activées, alors<digit>
alorsRemplacez
%~[modifiers]<digit>
par la valeur d'argument modifiée (remplacez par rien si non défini ou si spécifié $ PATH: le modificateur n'est pas défini) et continuez l'analyse.Remarque: les modificateurs sont insensibles à la casse et peuvent apparaître plusieurs fois dans n'importe quel ordre, sauf $ PATH: le modificateur ne peut apparaître qu'une seule fois et doit être le dernier modificateur avant le
<digit>
regardez la chaîne de caractères suivante, coupant avant
%
ou à la fin du tampon, et appelez-les VAR (peut être une liste vide)%
alorsremplacez
%VAR%
par la valeur de VAR et poursuivez l'analyseSupprimer
%VAR%
et continuer l'analyseregardez la chaîne de caractères suivante, interrompant avant
%
:
ou à la fin du tampon, et appelez-les VAR (peut-être une liste vide). Si VAR est interrompu avant:
et que le caractère suivant est%
alors inclus:
comme dernier caractère dans VAR et interrompu avant%
.%
alorsremplacez
%VAR%
par la valeur de VAR et poursuivez l'analyseSupprimer
%VAR%
et continuer l'analyse:
alorssupprimez
%VAR:
et poursuivez l'analyse.~
alors[integer][,[integer]]%
thenRemplacez-la
%VAR:~[integer][,[integer]]%
par la sous-chaîne de valeur de VAR (résultant éventuellement en une chaîne vide) et continuez l'analyse.=
ou*=
alors Lasyntaxe de recherche et de remplacement de variable non valide génère une erreur fatale: toutes les commandes analysées sont abandonnées et le traitement par lots s'interrompt s'il est en mode batch!
[*]search=[replace]%
, où la recherche peut inclure n'importe quel jeu de caractères sauf=
, et remplacer peut inclure n'importe quel jeu de caractères sauf%
, alorsRemplacer
%VAR:[*]search=[replace]%
par la valeur de VAR après avoir effectué la recherche et le remplacement (résultant éventuellement en une chaîne vide) et continuer analyseSupprimer
%
et continuer l'analyse en commençant par le caractère suivant après le%
%
début et continuer le balayage en commençant par le caractère suivant après le début conservé%
Ce qui précède aide à expliquer pourquoi ce lot
Donne ces résultats:
Remarque 1 - La phase 1 a lieu avant la reconnaissance des déclarations REM. Ceci est très important car cela signifie que même une remarque peut générer une erreur fatale si elle a une syntaxe d'expansion d'argument invalide ou une syntaxe de recherche et de remplacement de variable invalide!
Note 2 - Autre conséquence intéressante des règles d'analyse%: Les variables contenant: dans le nom peuvent être définies, mais elles ne peuvent être développées que si les extensions de commande sont désactivées. Il y a une exception: un nom de variable contenant un simple deux-points à la fin peut être développé pendant que les extensions de commande sont activées. Cependant, vous ne pouvez pas effectuer de sous-chaînes ni d'opérations de recherche et de remplacement sur les noms de variables se terminant par deux-points. Le fichier de commandes ci-dessous (gracieuseté de jeb) illustre ce comportement
Note 3 - Un résultat intéressant de l'ordre des règles d'analyse que jeb expose dans son article: Lors de l'exécution de rechercher et de remplacer avec une expansion retardée, les caractères spéciaux dans les termes de recherche et de remplacement doivent être échappés ou entre guillemets. Mais la situation est différente pour l'expansion en pourcentage - le terme de recherche ne doit pas être échappé (bien qu'il puisse être cité). La chaîne de pourcentage de remplacement peut nécessiter ou non un échappement ou une citation, selon votre intention.
Règles d'expansion retardée
Voici une explication développée et plus précise de la phase 5 dans la réponse de jeb (valable à la fois pour le mode batch et le mode ligne de commande)
Phase 5) Expansion retardée
Cette phase est ignorée si l'une des conditions suivantes s'applique:
CALL
aucun bloc entre parenthèses, à aucune forme de concaténation de commande (&
,&&
ou||
) ou à un tube|
.Le processus d'expansion différée est appliqué aux jetons indépendamment. Une commande peut avoir plusieurs jetons:
for ... in(TOKEN) do
if defined TOKEN
if exists TOKEN
if errorlevel TOKEN
if cmdextversion TOKEN
if TOKEN comparison TOKEN
Où la comparaison est l' une==
,equ
,neq
,lss
,leq
,gtr
, ougeq
Aucune modification n'est apportée aux jetons qui n'en contiennent pas
!
.Pour chaque jeton qui en contient au moins un
!
, scannez chaque caractère de gauche à droite pour^
ou!
, et s'il est trouvé, alors!
ou^
littéraux^
alors^
!
, alorsregardez la chaîne de caractères suivante, avant
!
ou<LF>
, et appelez-les VAR (peut être une liste vide)!
alorsremplacez
!VAR!
par la valeur de VAR et poursuivez l'analyseSupprimer
!VAR!
et continuer l'analyseRegardez chaîne de caractères suivante, avant la rupture
!
,:
ou<LF>
, et appelez les VAR (peut être une liste vide). Si VAR est interrompu avant:
et que le caractère suivant est!
alors inclus:
comme dernier caractère dans VAR et interrompu avant!
!
alorsremplacez
!VAR!
par la valeur de VAR et poursuivez l'analyseSupprimer
!VAR!
et continuer l'analyse:
alorssupprimer
!VAR:
et continuer l'analyse~
alors[integer][,[integer]]!
then Remplacez!VAR:~[integer][,[integer]]!
par la sous-chaîne de valeur de VAR (résultant éventuellement en une chaîne vide) et continuez l'analyse.[*]search=[replace]!
, où la recherche peut inclure n'importe quel jeu de caractères sauf=
, et remplacer peut inclure n'importe quel jeu de caractères sauf!
, alorsRemplacer
!VAR:[*]search=[replace]!
par la valeur de VAR après avoir effectué la recherche et le remplacement (résultant éventuellement en une chaîne vide) et continuer l'analyse!
Else conserve le
!
!
la source
%definedVar:a=b%
vs%undefinedVar:a=b%
et les%var:~0x17,-010%
formulaires%<digit>
,%*
ou%~
. Et le comportement change pour les variables non définies. Vous devez peut-être ouvrir une deuxième réponseComme indiqué, les commandes reçoivent la chaîne d'arguments entière dans μSoft land, et c'est à elles de l'analyser en arguments séparés pour leur propre usage. Il n'y a pas de cohérence entre les différents programmes et il n'y a donc pas un ensemble de règles pour décrire ce processus. Vous devez vraiment vérifier chaque cas de coin pour la bibliothèque C utilisée par votre programme.
En ce qui concerne les
.bat
fichiers système , voici ce test:Nous pouvons maintenant exécuter des tests. Voyez si vous pouvez comprendre ce que μSoft essaie de faire:
Très bien jusqu'à présent. (Je vais laisser de côté l'inintéressant
%cmdcmdline%
et à%0
partir de maintenant.)Aucune extension de nom de fichier.
Pas de suppression des guillemets, bien que les guillemets empêchent le fractionnement des arguments.
Les guillemets doubles consécutifs leur font perdre toutes les capacités d'analyse spéciales qu'ils auraient pu avoir. L'exemple de @ Beniot:
Quiz: Comment passez-vous la valeur d'une variable d'environnement en tant qu'argument unique (c.-à-d. As
%1
) à un fichier bat?Une analyse saine semble à jamais interrompue.
Pour vos loisirs, essayez d' ajouter divers
^
,\
,'
,&
(etc.). Caractères à ces exemples.la source
t
c'esta "b c
. Avez - vous une recette pour obtenir ces 6 caractères (a
2 × espace,"
,b
etc
apparaître) comme%1
dans un.cmd
? J'aime ta réflexion.args "%t:"=""%"
est assez proche :-)Vous avez déjà quelques bonnes réponses ci-dessus, mais pour répondre à une partie de votre question:
Ce qui se passe là-bas, c'est que parce que vous avez un espace avant le =, une variable est créée appelée
%a<space>%
ainsi lorsque vousecho %a %
qui est évaluée correctement commeb
.La partie restante
b% c%
est ensuite évaluée en tant que texte brut + une variable non définie% c%
, qui devrait être renvoyée en écho comme tapée, pour moiecho %a %b% c%
renvoiebb% c%
Je soupçonne que la possibilité d'inclure des espaces dans les noms de variables est plus un oubli qu'une `` fonctionnalité '' prévue
la source
edit: voir la réponse acceptée, ce qui suit est faux et explique seulement comment passer une ligne de commande à TinyPerl.
Concernant les citations, j'ai le sentiment que le comportement est le suivant:
"
est trouvé, le globbing de chaîne commence"
est globulé"
est trouvé:""
(donc un triple"
) alors un guillemet double est ajouté à la chaîne"
(donc un double"
), alors un guillemet double est ajouté à la chaîne et la chaîne de caractères se termine"
, le balayage des chaînes se termineEn bref:
"a """ b "" c"""
se compose de deux chaînes:a " b "
etc"
"a""
,"a"""
et"a""""
sont tous la même chaîne si à la fin d'une lignela source
Notez que Microsoft a publié le code source de son terminal. Il peut fonctionner de la même manière que la ligne de commande en ce qui concerne l'analyse syntaxique. Peut-être que quelqu'un est intéressé à tester les règles d'analyse par rétro-ingénierie conformément aux règles d'analyse du terminal.
Lien vers le code source.
la source