Passer au contenu principal

Compatibilité CMD et CMDebug / TCC-RT, partie 2

Après ma demande de fichiers batch CMD qui ne fonctionnaient pas avec CMDebug or TCC, un utilisateur m'a envoyé un fichier batch avec une utilisation curieuse de la syntaxe d'expansion de variable retardée CMD.

CMD prend en charge le !var! syntaxe pour retarder l’expansion des variables au moment de l’exécution d’une commande, plutôt que lorsque l’instruction est lue. Par exemple, supposons que vous souhaitiez créer une liste de tous les fichiers d'un répertoire. Votre premier essai pourrait ressembler à ceci :

définir FICHIERS=

pour %f dans (*), définissez FILES=%FILES% %f

Maintenant, cela fonctionnera dans CMDebug et TCC, mais ça va ne sauraient  travailler en CMD. La raison est que CMD finit par exécuter ceci :

[code]pour %f dans (*) définissez FILES= %f[/code]

et vous vous retrouvez avec une liste contenant uniquement le dernier fichier du répertoire.

Microsoft a donc ajouté l'option permettant de retarder l'expansion des variables dans CMD (configurable soit au démarrage, soit avec la commande SETLOCAL). Ce n'est pas nécessaire dans TCC fichiers batch, mais il est pris en charge dans TCC et CMDebug par souci de compatibilité.

Alors depuis TCC déjà pris en charge cela, quelle était l'incompatibilité ? Le problème venait de cette ligne :

définissez "regVal=!regVal:%%=?!"

et un correspondant :

définissez "regVal=!regVal:?=%%!"

Quel est le but ici ? Le code remplace un ? pour chaque % dans la variable, puis en inversant la substitution. Pourquoi utiliser l'expansion de variable retardée, puisqu'il ne s'agit pas d'une instruction IF ou FOR ou d'un groupe de commandes, et que la valeur ne va pas changer entre le moment où la ligne a été lue et la ligne a été exécutée ?

Parce que CMD ne peut pas gérer quelque chose comme ça :

définir "regVal=%regVal:%%=?%"

Il mettra fin à l'argument à la première correspondance %, donc vous obtenez ceci :

définir "regVal=%regVal:%"

OK, alors pourquoi ne pas simplement échapper au % personnage que vous souhaitez remplacer ?

définir "regVal=%regVal:^%=?%"

Cela fonctionne bien dans TCC et CMDebug, mais échoue dans CMD. (Il peut s'agir d'un bug, ou simplement d'un comportement non pris en charge – la documentation CMD ne le mentionne pas.) Le développeur a donc utilisé une extension de variable retardée pour empêcher le problème. % d'être interprété comme entourant le nom de la variable. Lorsque CMD a évalué la ligne, il a constaté un doublement %, qu'il a converti en un seul %, et la ligne a été exécutée comme :

définissez "regVal=!regVal:%=?!"

Alors pourquoi cela n'a-t-il pas fonctionné avec TCC? Parce que TCC Je ne m'attendais pas à trouver un intrus % caractère à l’intérieur d’une chaîne de substitution dans une variable à expansion retardée. Parce que pourquoi ferais-tu ça ? Aucune raison, sauf si vous souhaitez remplacer % caractères dans CMD, et vous n’avez pas pu le faire de la manière attendue. (Il existe plusieurs façons de procéder dans TCC, tous plus compréhensibles que cette syntaxe torturée.)

J'ai ajouté la prise en charge de cette syntaxe CMD aux versions actuelles de TCC, TCC-RT, et CMDebug.

Continuez à envoyer ces fichiers batch CMD farfelus !