El patrón ENDLOCAL & SET VAR=%TEMPVAR%
es clásico. Pero hay situaciones en las que no es ideal.
Si no conoce el contenido del TempVar, a continuación, usted podría encontrarse con problemas si el valor contiene caracteres especiales como <
>
&
o |
. En general, puede protegerse contra eso mediante el uso de comillas como SET "VAR=%TEMPVAR%"
, pero eso puede causar problemas si hay caracteres especiales y el valor ya está citado.
Una expresión FOR es una excelente opción para transportar un valor a través de la barrera ENDLOCAL si le preocupan los caracteres especiales. La expansión retrasada debería estar habilitada antes de la ENDLOCAL y deshabilitada después de la ENDLOCAL.
setlocal enableDelayedExpansion
set "TEMPVAR=This & "that ^& the other thing"
for /f "delims=" %%A in (""!TEMPVAR!"") do endlocal & set "VAR=%%~A"
Limitaciones:
Si expansión retardada se habilita después de la ENDLOCAL, entonces el valor final será dañada si la TempVar contenía !
.
valores que contienen un carácter de avance de línea no pueden ser transportados
Si debe devolver varios valores, y usted sabe de un carácter que no puede aparecer en cualquiera de los valores, a continuación, sólo tiene que utilizar el apropiado para las opciones/F. Por ejemplo, si sé que los valores no pueden contener |
:
setlocal enableDelayedExpansion
set "temp1=val1"
set "temp2=val2"
for /f "tokens=1,2 delims=|" %%A in (""!temp1!"|"!temp2!"") do (
endLocal
set "var1=%%~A"
set "var2=%%~B"
)
Si debe devolver múltiples valores, y el juego de caracteres no está restringido, a continuación, utilizar For anidados/F bucles:
setlocal enableDelayedExpansion
set "temp1=val1"
set "temp2=val2"
for /f "delims=" %%A in (""!temp1!"") do (
for /f "delims=" %%B in (""!temp2!"") do (
endlocal
set "var1=%%~A"
set "var2=%%~B"
)
)
Definitivamente echa un vistazo a jeb's answer para una técnica segura, a prueba de balas que funciona para todos los valores posibles en todas las situaciones.
2017-08-21 - Nueva función RETURN.BAT
He trabajado con DosTips usuario jeb para desarrollar a batch utility called RETURN.BAT que se puede utilizar para salir de la secuencia de comandos o llama programación y retornar una o más variables a través de la barrera ENDLOCAL. Muy bueno :-)
A continuación se muestra la versión 3.0 del código. Lo más probable es que no mantenga este código actualizado. Lo mejor es seguir el enlace para asegurarse de obtener la última versión y ver ejemplos de uso.
RETURN.BAT
::RETURN.BAT Version 3.0
@if "%~2" equ "" (goto :return.special) else goto :return
:::
:::call RETURN ValueVar ReturnVar [ErrorCode]
::: Used by batch functions to EXIT /B and safely return any value across the
::: ENDLOCAL barrier.
::: ValueVar = The name of the local variable containing the return value.
::: ReturnVar = The name of the variable to receive the return value.
::: ErrorCode = The returned ERRORLEVEL, defaults to 0 if not specified.
:::
:::call RETURN "ValueVar1 ValueVar2 ..." "ReturnVar1 ReturnVar2 ..." [ErrorCode]
::: Same as before, except the first and second arugments are quoted and space
::: delimited lists of variable names.
:::
::: Note that the total length of all assignments (variable names and values)
::: must be less then 3.8k bytes. No checks are performed to verify that all
::: assignments fit within the limit. Variable names must not contain space,
::: tab, comma, semicolon, caret, asterisk, question mark, or exclamation point.
:::
:::call RETURN init
::: Defines return.LF and return.CR variables. Not required, but should be
::: called once at the top of your script to improve performance of RETURN.
:::
:::return /?
::: Displays this help
:::
:::return /V
::: Displays the version of RETURN.BAT
:::
:::
:::RETURN.BAT was written by Dave Benham and DosTips user jeb, and was originally
:::posted within the folloing DosTips thread:
::: http://www.dostips.com/forum/viewtopic.php?f=3&t=6496
:::
::==============================================================================
:: If the code below is copied within a script, then the :return.special code
:: can be removed, and your script can use the following calls:
::
:: call :return ValueVar ReturnVar [ErrorCode]
::
:: call :return.init
::
:return ValueVar ReturnVar [ErrorCode]
:: Safely returns any value(s) across the ENDLOCAL barrier. Default ErrorCode is 0
setlocal enableDelayedExpansion
if not defined return.LF call :return.init
if not defined return.CR call :return.init
set "return.normalCmd="
set "return.delayedCmd="
set "return.vars=%~2"
for %%a in (%~1) do for /f "tokens=1*" %%b in ("!return.vars!") do (
set "return.normal=!%%a!"
if defined return.normal (
set "return.normal=!return.normal:%%=%%3!"
set "return.normal=!return.normal:"=%%4!"
for %%C in ("!return.LF!") do set "return.normal=!return.normal:%%~C=%%~1!"
for %%C in ("!return.CR!") do set "return.normal=!return.normal:%%~C=%%2!"
set "return.delayed=!return.normal:^=^^^^!"
) else set "return.delayed="
if defined return.delayed call :return.setDelayed
set "return.normalCmd=!return.normalCmd!&set "%%b=!return.normal!"^!"
set "return.delayedCmd=!return.delayedCmd!&set "%%b=!return.delayed!"^!"
set "return.vars=%%c"
)
set "err=%~3"
if not defined err set "err=0"
for %%1 in ("!return.LF!") do for /f "tokens=1-3" %%2 in (^"!return.CR! %% "") do (
(goto) 2>nul
(goto) 2>nul
if "^!^" equ "^!" (%return.delayedCmd:~1%) else %return.normalCmd:~1%
if %err% equ 0 (call) else if %err% equ 1 (call) else cmd /c exit %err%
)
:return.setDelayed
set "return.delayed=%return.delayed:!=^^^!%" !
exit /b
:return.special
@if /i "%~1" equ "init" goto return.init
@if "%~1" equ "/?" (
for /f "tokens=* delims=:" %%A in ('findstr "^:::" "%~f0"') do @echo(%%A
exit /b 0
)
@if /i "%~1" equ "/V" (
for /f "tokens=* delims=:" %%A in ('findstr /rc:"^::RETURN.BAT Version" "%~f0"') do @echo %%A
exit /b 0
)
@>&2 echo ERROR: Invalid call to RETURN.BAT
@exit /b 1
:return.init - Initializes the return.LF and return.CR variables
set ^"return.LF=^
^" The empty line above is critical - DO NOT REMOVE
for /f %%C in ('copy /z "%~f0" nul') do set "return.CR=%%C"
exit /b 0
Me encantan todas las respuestas a continuación que muestran cómo manejar todo tipo de casos extremos que no entrarán en juego con su pregunta específica. (El resultado final debe ser un directorio legal, por lo que es poco probable que tenga '!' O ';' u otras rarezas de metacaracteres). Demuestra que a todos nos preocupa más la enseñanza que simplemente contentarnos rápidamente con una respuesta. Y eso, mis amigos, es StackOverflow. –
Respondí esto usando el registro reg.exe y el volátil aquí: https://stackoverflow.com/questions/26246151/setlocal-enabledelayedexpansion-causes-cd-and-pushd-to-not-persist/45369743#45369743 – mosh
Curiosamente , Sospecho que el script llamado solo necesita referenciar su propia ruta, IE, "Activate.bat" necesita saber de dónde fue llamada, y usar esa variable asignada como "Scripts" para futuras llamadas dentro de sí misma. –