2009-07-29 9 views
11

CMD je peux développer deux fois une variable comme suit:Comment développer une ligne de commande Utiliser Windows XP variable shell CMD deux fois (récursive)

set AAA=BBB 
set BBB=CCC 
for /F "usebackq tokens=*" %i in (`echo %%AAA%%`) do echo %i 

fera écho CCC. C'est à dire. AAA a été étendu à la chaîne BBB, puis la variable BBB a été étendue à CCC.

Cela ne fonctionne pas à l'intérieur d'un script de traitement par lots (c'est-à-dire un fichier .cmd). Changer le %%AAA%% en %%%AAA%%% ou en %%%%AAA%%%% ne fonctionne pas non plus.

Une idée de comment je peux réaliser ceci à partir d'un script, à savoir prendre la variable AAA à la chaîne CCC?

Modifier la fin

Les réponses affichées travail pour mon exemple réduit cependant la réponse non tortueuse ne fonctionne pas pour le cas réel. Voici un exemple étendu (qui ne fonctionne pas), qui illustre ce que je en train d'essayer de le faire:

setlocal enabledelayedexpansion 

set LIST=BBB CCC DDD 
set BBB=111 
set CCC=222 
set DDD=333 

for %%i in (%LIST%) do (

    for /F %%a in ('echo %%%i%') do echo !%%a! 

) 

Je voudrais voir

111 
222 
333 
sortie

.

+0

dinged parce que vous sont toujours dans un fichier batch et n'utilise pas PowerShell. ;) – Cheeso

+1

Impossible d'utiliser PowerShell, pas encore au moins. –

+0

Est-ce pas votre déclaration * Les réponses ont affiché du travail pour mon exemple réduit mais la réponse non-tortueuse ne fonctionne pas pour le cas réel * en contradiction avec Votre commentaire à * akf * * Merci, les deux travail.*? –

Répondre

12

En pensant en termes d'une solution moins tortueuse, cela produit aussi le CCC que vous désirez.

setlocal enabledelayedexpansion 
set AAA=BBB 
set BBB=CCC 
for /F %%a in ('echo %AAA%') do echo !%%a! 

modifier:

disséquer cette réponse:

setlocal enabledelayedexpansion - cela permettra de tout paramètre variable d'environnement au cours de votre chauve-souris à utiliser tel que modifié au cours du processus de la boucle for.

set AAA=BBB, set BBB=CCC - votre population de données set déclarations

for /F %%a in ('echo %AAA%') do echo !%%a! - Ceci indique que le processeur boucle, mais une seule fois, et de prendre le premier jeton qui est retourné (delimiter par défaut de l'espace et onglet appliquer) de la lancer la commande dans les parens et la mettre dans la var %% a (en dehors d'un batch, un seul% fera l'affaire). Si vous spécifiez var comme %% a, vous devez utiliser %% a dans votre bloc do. De même, si vous spécifiez %% i, utilisez %% i dans votre bloc do. Notez que pour que votre variable d'environnement soit résolue dans le bloc do de la boucle for, vous devez l'entourer dans !. (vous n'avez pas besoin de le faire dans le bloc in, comme je l'ai posté à l'origine - j'ai fait ce changement dans mon édition).

modifier:

Vous étiez très proche avec votre exemple mis à jour. Essayez comme ceci:

@echo off 
setlocal enabledelayedexpansion 
set LIST=BBB CCC DDD 
set BBB=111 
set CCC=222 
set DDD=333 

for %%i in (%LIST%) do (
    for /F %%a in ('echo %%i') do echo !%%a! 
) 

La différence entre votre mise à jour et ce que vous essayez de faire écho la variable d'environnement dans le in ensemble avec in ('echo %%%i%'), mais sans les ! « s pour l'expansion retardée de variables définies. Si vous utilisiez in ('echo !%%i!'), vous verriez vos variables BBB, CCC et DDD résolues, mais alors le bloc do de votre boucle interne n'aurait rien à résoudre - vous n'avez aucune variable d'environnement 111. Avec cela à l'esprit, vous pouvez simplifier la boucle avec les éléments suivants:

@echo off 
setlocal enabledelayedexpansion 
set LIST=BBB CCC DDD 
set BBB=111 
set CCC=222 
set DDD=333 

for %%i in (%LIST%) do (echo !%%i!) 
+0

Bien que ce soit effectivement moins tortueux, le var que j'utilise actuellement fait partie d'une boucle for, par exemple. au lieu de AAA j'ai i: pour %% i dans (% LIST%) faire ( :: utiliser i Pour ce cas, le remplacement de je pour AAA dans votre solution ne semble pas fonctionner.Toutes les idées? –

+0

Je suis Je ne suis pas sûr que je suis ce que vous dites: lorsque vous utilisez la variable var d'une boucle 'for' dans une chauve-souris, le double% devrait faire l'affaire.J'ai utilisé %% a, ce qui serait le même que %% i dans votre exemple Peut-être pourriez-vous inclure votre exemple plus spécifique dans la question – akf

+0

J'ai ajouté un autre exemple à la question: –

3

L'approche suivante (tortueuse) semble fonctionner bien:

@echo off 
:main 
    setlocal enableextensions enabledelayedexpansion 
    set aaa=bbb 
    set bbb=ccc 
    call :myset x %%aaa%% 
    echo %x% 
    endlocal 
    goto :eof 
:myset 
    for /F "usebackq tokens=*" %%i in (`echo %%%2%%`) do set %1=%%i 
    goto :eof 

Il produit:

ccc 

comme vous le souhaitez. J'ai souvent utilisé cette astuce pour (par exemple) formater %aaa% en %x% à une certaine taille (la sprintf) mais c'est la première fois que j'ai dû faire une double indirection. Cela fonctionne parce que vous ne trouvez pas le "%%" supplémentaire étant aspiré par le niveau actuel de la coquille.

+0

Quel extra '%%' Avez-vous en tête? –

0

La double indirection (ce qui est un moyen très approprié pax l'a mis) rappelle le pointeur C de référence.
Je doute que cela est pris en charge dans le Windows command shell.

Pensez-vous que le but plus large que vous ciblez peut être atteint avec quelque chose de plus facile;
peut-être moindre d'un code-golf approche alors l'un bien conçu par pax?

+0

Probablement, je pense que cela nécessiterait une question distincte, sinon les réponses actuelles n'auront pas de sens. –

3

Ce aaa.bat

@echo off 
set aaa=bbb 
set bbb=ccc 
for /F %%i in ('echo %%%aaa%%%') do echo %%i 

sorties

c:>ccc 

Quel est exactement le problème?

+0

Si vous l'essayez avec des lettres majuscules pour les noms de variables selon mon exemple, cela ne fonctionne pas. Vous obtenez% CCC%. –

+0

@jonh. J'ai essayé le script ci-dessus sur Vista après avoir changé 'aaa' en' AAA' et 'bbb' en' BBB' et la sortie est 'ccc'. –

+0

@Piotr. J'utilisais XP à l'époque –

7

Comment développer une variable shell plusieurs fois:

@echo off 
setlocal enabledelayedexpansion 

set myvar=second 
set second=third 
set third=fourth 
set fourth=fifth 

echo Variable value before expansion: !myvar! 
call :expand myvar 
echo Variable value after expansion: !myvar! 
goto :eof 


:expand 
    set var=%1 
    :expand_loop 
     if not "!%var%!" == "" (
      set var=!%var%! 
      goto :expand_loop 
     ) 
     set %1=!var! 
    goto :eof 

sortie:

Variable value before expansion: second 
Variable value after expansion: fifth 
+1

Suivi: [Pourquoi l'expansion retardée d'un fichier de traitement par lots ne fonctionne-t-elle pas dans ce cas?] (Http://stackoverflow.com/questions/7882395/) –

0

il semble que la meilleure chose à faire est de créer un petit fichier temporaire pour définir la variable que vous souhait. quelque chose comme ceci devrait fonctionner:

setlocal enabledelayedexpansion 

set LIST=BBB CCC DDD 
set BBB=111 
set CCC=222 
set DDD=333 

for %%i in (%LIST%) do (
    echo set a=\%%%i\%>tmp.bat 
    call tmp.bat 
    echo %a 
    rm tmp.bat 
) 
1

Ceci est une question un peu datée, mais, fait intéressant, la réponse est plus simple maintenant.Je l'exécution de ces scripts sur Windows 10:

setlocal enabledelayedexpansion 
set AAA=BBB 
set BBB=CCC 
echo !%AAA%! 

sorties

CCC 

Pour la version étendue, cela fonctionne:

setlocal enabledelayedexpansion 
set LIST=BBB CCC DDD 
set BBB=111 
set CCC=222 
set DDD=333 
for %%i in (%LIST%) do (
    echo !%%i! 
) 

sorties

111 
222 
333 
Questions connexes