2011-10-05 49 views
1

我试图在Delayed Variable Expansion中使用动态变量来表示其他动态变量。我遇到了一些麻烦。如果动态变量的值是具有自己的值的另一个动态变量,如何获得动态变量的值?批处理中递归动态变量的返回值

即!valA! =%valB%=这

@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 

任何帮助,将不胜感激。

+0

Woot!博士学位批处理脚本。我认为每个人都已经起来,最近用PowerShell去了 – sehe

+0

我很好奇这行:“SET _temp =!%_ temp%!”。你能解释你想做什么吗? – Arun

+0

@Arun将_temp重新赋给当前的_temp(这是一个变量名)值。 – seantmanley

回答

1

逻辑上发生故障的代码等同于

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

正如已经在以前的答案和评论所指出的,你可以将值赋给VAR2,然后在同一代码块中使用%VAR2%访问该值,因为%VAR2%在代码块的解析阶段被展开,此时该值不是您想要的值(可能未定义) 。

但是除了!VAR2以外,您还需要第二级扩展!得到你想要的结果。我知道三种解决方案。

1)该解决方案有效,但不推荐使用,因为速度较慢。

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

在执行CALL之前,每个%%减少到%,而!VAR2!变成VAR1。 因此,被调用的语句变为set VAR3=%VAR1%,并且调用的语句通过%var%扩展阶段进行重新清理,因此您可以得到期望的结果。

但是 - CALL是相对非常昂贵的。在循环中使用时,可能会导致严重的性能下降。杰布在提供CALL me, or better avoid call

1A)了良好的示范和解释有一种情况,你叫的CALL解决方案的变化:标记子程序。由于子程序在调用后被解析,因此您可以简单地使用set VAR3=!%VAR2%!。但是,这又一次使用CALL,因此它相对较慢并且不被推荐。

2)此一般的解决方案的工作原理,并且是MUCH相比更快。它使用FOR变量进行第二级扩展。这是推荐的解决方案。

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

3)如果VAR1的值已知是一个整数,则存在使用SET /A

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

的SET的特例溶液/ A命令具有其自己的内置在膨胀在延迟扩展之后发生的变量,并且不需要标点符号。

+0

我最终以另一种方式解决了这个问题,但是我忘记了是什么原因,因为我离开了这个工作。 – seantmanley

+0

我想我在重读这篇文章后撒谎了。我不确定,但我想 - 我沿着#2 @dbenham的路线走了一些东西。我记得我花了几天的时间仔细研究并开始工作。我会试着去查看一些旧脚本,这样我就可以看到我实际上做了什么。感谢很久以前的帮助。 :) – seantmanley

0

您的代码在SET _temp=!%_temp%!上失败,因为在解析括号块时评估百分比展开。

你可以将其更改为

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

顺便说一句。如果你的样本被减少到最小代码的话,这将会容易得多。

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

这只适用于括号内。

为了更好地理解不同的膨胀是如何工作的,
您可以阅读How does the Windows Command Interpreter (CMD.EXE) parse scripts?

+0

代码块是从一个较大的代码块中分析出来的,这些代码在使用对其他函数的调用时不会与其他人发挥出色。这就是生活。干杯。 – seantmanley

+0

但是第一个变体应该在你的代码中工作 – jeb