2011-10-05 51 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