2015-02-23 3 views
2

Как сохранить число переменных (с определенным префиксом) в прошлом endlocal в цикле?Назначить переменные, прошедшие через endlocal в цикле

Переменные видимы в декларации цикла, но не в теле.

Ниже приведен пример с echo вместо назначения переменных, чтобы проиллюстрировать, что переменные не видны в теле for. Обычно присвоение переменной будет идти вместо echo:

@echo off 

setlocal ENABLEDELAYEDEXPANSION 
set TB_1=test1 
set TB_2=test2 

set TB_ALL_VARS= 
for /F "tokens=1 delims==" %%x in ('set TB_') do (
    set TB_ALL_VARS=%%x !TB_ALL_VARS! 
) 

for %%x in (%TB_ALL_VARS%) do (echo %%x = !%%x!) 
echo END LOCAL 
endlocal & (for %%x in (%TB_ALL_VARS%) do (echo %%x = !%%x!)) 

Выход:

TB_2 = test2 
TB_1 = test1 
END LOCAL 
TB_2 = !TB_2! 
TB_1 = !TB_1! 

Как вы можете видеть, переменные печатаются в порядке, прежде чем Endlocal, но не печатается после Endlocal.

Есть ли способ сохранить переменные, подобные этому прошлому endlocal?

ответ

4

Учитывая ваш пример кода, я думаю, что вы спрашивают: «Как установить динамическое число переменных после endlocal?» То, что вы просите, не очень интуитивно, но это возможно. Вы не можете использовать задержанное расширение при составлении set с endlocal. Обходной путь часто можно использовать для использования цикла for для endlocal & set "var=%%A", который работает только в том случае, если количество переменных и значений является статическим. К сожалению, endlocal & for не работает так же, как for... in... do (endlocal & set), как вы, несомненно, обнаружили в своем собственном тестировании.

Мое решение использовать макрос, чтобы сделать установку после endlocal - в основном ввод команды, а не простые строковые значения в переменную, а затем оценить эту переменную как набор set команд.

@echo off 
setlocal 

:: // call ":set" subroutine to do the setting 
call :set 

:: // display results 
set subv 

:: // end main runtime 
goto :EOF 


:: // :set subroutine 
:set 
setlocal enabledelayedexpansion 

:: // any number of variables prefixed by "subv" 
set "subv1=1" 
set "subv2=2" 
set "subv3=3" 

:: // init %compound% 
set compound= 

:: // combine all %subvX% variables into a macro of set var1=val1 & set var2=val2, etc 
for /f "delims=" %%I in ('set subv') do set "compound=!compound! & set "%%~I"" 

:: // evaluate set commands as a macro 
endlocal & %compound:~3% 
goto :EOF 

Другие решения, чтобы вернуться к первому обходного я уже говорил, в формате endlocal & set "var=%%A". Как правило, используется только тогда, когда вы знаете, вы будете только петля один раз, что-то вроде

for %%I in ("!var!") do endlocal & set "return=%%~I" 

... потому что вы не хотите Endlocal слишком много раз. Но вы можете сделать несколько цикла значение с одним endlocal, используя if not defined так:

@echo off 
setlocal 

call :set 
set subv 

goto :EOF 

:set 
setlocal enabledelayedexpansion 
set "subv1=1" 
set "subv2=2" 
set "subv3=3" 
set end= 
for /f "delims=" %%I in ('set subv') do (
    if not defined end endlocal & set end=1 
    set "%%~I" 
) 
goto :EOF 

... и потому, что endlocal и set "%%~I" содержатся в вводном блоке кода, переменные повторно установить и ваша цель Достигнут.

3

Вы пытаетесь использовать tunneling, но после того, как Endlocal вы не можете использовать ! расширить variables.Try это:

@echo off 

setlocal ENABLEDELAYEDEXPANSION 
set TB_1=test1 
set TB_2=test2 

set TB_ALL_VARS= 
for /F "tokens=1 delims==" %%x in ('set TB_') do (
    set TB_ALL_VARS=%%x !TB_ALL_VARS! 
) 

for %%x in (%TB_ALL_VARS%) do (echo %%x = !%%x!) 
echo END LOCAL 
endlocal & (for %%x in (%TB_ALL_VARS%) do (call echo %%x = %%%%x%%)) 

ИЛИ

@echo off 

setlocal ENABLEDELAYEDEXPANSION 
set TB_1=test1 
set TB_2=test2 

set TB_ALL_VARS= 
for /F "tokens=1 delims==" %%x in ('set TB_') do (
    set TB_ALL_VARS=%%x !TB_ALL_VARS! 
) 

for %%x in (%TB_ALL_VARS%) do (echo %%x = !%%x!) 
echo END LOCAL 
endlocal & (for %%x in (%TB_ALL_VARS%) do (
setlocal enableDelayedExpansion 
call echo %%x = !%%x!) 
endlocal 
) 
+0

Я пробовал оба, но ни одно из этих решений не работало – Rado