Return Values of Recursive Dynamic Variables in Batch

六眼飞鱼酱① 提交于 2019-12-23 03:48:06

问题


I'm attempting to use dynamic variables within Delayed Variable Expansion to represent other Dynamic Variables. I'm running into some trouble. How can I get a dynamic variable's value's value if the dynamic variable's value is another dynamic variable with it's own value?

i.e. !valA! = %valB% = this

@ECHO OFF
SETLOCAL EnableExtensions EnableDelayedExpansion
...
...
FOR /F ... %%G IN (...) DO (
    SET _temp=%%~nG
    SET _file=!_temp:~0,-4!
    SET _cnt=0
    FOR /F ... %%L IN (...) DO (
        SET _temp=%%L
        SET _str=!_temp:*: =!
        SET /A _cnt+=1
        SET _temp=x!_file!!_cnt!
        IF DEFINED !_temp! (
            SET _temp=!%_temp%!
::
::_temp('s value) is _var('s value) is "xyz"
::Set new _temp to equal current _temp's "xyz"
::
            IF !_temp! NEQ !_str! (
                ECHO File Content Mismatch
            )
        ) ELSE (
            SET xvar=!_temp!
            SET !xvar!=!_str!
        )

    )
)
...
...
exit

Any help would be appreciated.


回答1:


Logically your failing code equates to

setlocal enableDelayedExpansion
(
  set VAR1=success
  set VAR2=VAR1
  set VAR3=!%VAR2%!
  echo VAR3=!VAR3!
)

As has already been pointed out in previous answers and comments, you can't assign a value to VAR2 and then access the value using %VAR2% within the same code block because %VAR2% is expanded during the parsing phase of the code block, at which point the value is not what you want (probably undefined).

But you need a second level of expansion in addition to !VAR2! to get the result you want. I know of three solutions.

1) This solution works, but it is not recommended because it is slow.

setlocal enableDelayedExpansion
(
  set VAR1=success
  set VAR2=VAR1
  call set VAR3=%%!VAR2!%%
  echo VAR3=!VAR3!
)

Prior to the execution of the CALL, each %% is reduced to %, and !VAR2! becomes VAR1. Thus the called statement becomes set VAR3=%VAR1%, and the called statement is reparsed through the %var% expansion phase, so you get your desired result.

BUT - CALL is relatively very expensive. When used in a loop it can cause severe performance degradation. jeb provides a good demonstration and explanation at CALL me, or better avoid call

1a) There is a variation of the CALL solution where you call a :LABELed subroutine. Because the subroutine is parsed after the call, you can simply use set VAR3=!%VAR2%!. But again, this uses CALL so it is relatively slow and not recommended.

2) This general solution works, and is MUCH faster in comparison. It uses a FOR variable for the second level of expansion. This is the recommended solution.

setlocal enableDelayedExpansion
(
  set VAR1=success
  set VAR2=VAR1
  for /f %%A in ("!VAR2!") do set VAR3=!%%A!
  echo VAR3=!VAR3!
)

3) If the value of VAR1 is known to be an integer, then there is a special case solution using SET /A

setlocal enableDelayedExpansion
(
  set VAR1=999
  set VAR2=VAR1
  set /a VAR3=!VAR2!
  echo VAR3=!VAR3!
)

The SET /A command has its own built in expansion of variables that takes place after delayed expansion, and no punctuation is needed.




回答2:


Your code fails at SET _temp=!%_temp%!, as the percent expansion is evaluated while parsing the parenthesis block.

You could change it to

set "varname=!_temp!"
set "content=!varname!"

Btw. It would be much easier, if your sample would be reduced to the minimum of code, like.

setlocal EnableDelayedExpansion
set "var1=content of var1"
set "var2=var1"
set "result=!%var2%!"
echo !result!

This only works as it isn't in brackets.

To better understand how the different expansions work,
you can read How does the Windows Command Interpreter (CMD.EXE) parse scripts?



来源:https://stackoverflow.com/questions/7668001/return-values-of-recursive-dynamic-variables-in-batch

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!