bat腳本-set(setlocal enabledelayedexpansion) 學習


設置本地為延遲擴展。其實也就是:延遲變量,全稱延遲環境變量擴展。

事件一:

@echo off
set a=4
set a=5&echo %a%
pause

 解說:為什么是4而不是5呢?在echo之前明明已經把變量a的值改成5了。

批處理運行命令的機制:批處理讀取命令時是按行讀取的(另外例如for命令等,其后用一對圓括號閉合的所有語句也當作一行),在處理之前要完成必要的預處理工作,這其中就包括對該行命令中的變量賦值。我們現在分析一下例1,批處理在運行到這句“set a=5&echo %a%”之前,先把這一句整句讀取並做了預處理——對變量a賦了值,那么%a%當然就是4了!(沒有為什么,批處理就是這樣做的。)而為了能夠感知環境變量的動態變化,批處理設計了變量延遲。簡單來說,在讀取了一條完整的語句之后,不立即對該行的變量賦值,而會在某個單條語句執行之前再進行賦值,也就是說“延遲”了對變量的賦值。如何開啟變量延遲呢?變量延遲又需要注意什么呢?

事件二:開啟 變量延遲機制!

@echo off 
setlocal enabledelayedexpansion 
set a=4 
set a=5&echo !a! 
pause

 結果:5
解說:由於啟動了變量延遲,得到了正確答案。變量延遲的啟動語句是“setlocal enabledelayedexpansion”,並且變量要用一對嘆號“!!”括起來(注意要用英文的嘆號),否則就沒有變量延遲的效果。分析一下例2,首先“setlocal enabledelayedexpansion”開啟變量延遲,然后“set a=4”先給變量a賦值為4,“set a=5&echo !a!”這句是給變量a賦值為5並輸出(由於啟動了變量延遲,所以批處理能夠感知到動態變化,即不是先給該行變量賦值,而是在運行過程中給變量賦值,因此此時a的值就是5了)。

 

事件三: (一般通過全局變量保存返回值的比較常見),當前這個示例通過變量傳遞來保存函數的返回值:

1 @echo off
2 ::通過給調用者傳遞一個變量(var),來保存函數的返回值
3 call :myFunc var
4 echo.var:%var%
5 goto :eof
6 
7 :myFunc
8     set "%1=haha"
9 goto :eof

結果:var:haha
解說:通過給 myFunc 函數傳遞 var 一個變量,然后 函數中 通過 set "%1=haha" 給第一個參數設置值,也就是給變量設置;

事件四: 通過 設置局部的可延遲的擴展變量 來實現循環,如下循環5次;

1 @echo off
2 ::設置局部的可延遲的擴展變量a
3 setlocal enabledelayedexpansion
4 for /l %%i in ( 1,1,5 ) do (
5     set a=%%i  echo !a!
6 )
7 pause

解釋: for /l %%i in(start,step,end) do  ;這個循環的語法;每次將循環變量賦值給a,並打印出來;必須要加 setlocal enabledelayedexpansion 這一句,否則 a變量 預處理時沒有這個東西,會不打印或者打印 echo是關閉狀態;

事件五:處理局部變量和全局變量不沖突;SETLOCAL命令能讓處理器當做是局部變量,用ENDLOCAL解除局部變量。

 1 @echo off
 2 :: 怎么保證局部變量和全局變量不沖突,SETLOCAL命令能讓處理器當做是局部變量,
 3 :: 用ENDLOCAL解除局部變量。
 4 :: ENDLOCAL 會被自動調用,當批處理執行到文件末尾的時候,即GOTO:EOF。
 5 :: SETLOCAL可以很好的保護函數內與外面的變量不會沖突。
 6 
 7 set "var1=i'm goloable var1!"
 8 set "var2=i'm goloable var2!"
 9 
10 echo.var1 before:"%var1%"
11 echo.var2 before:"%var2%"
12 call :myFunc var2
13 echo.var1 after:"%var1%"
14 echo.var2 after:"%var2%"
15 pause && goto :eof
16 ::傳一個參數應用進去
17 :myFunc
18 SETLOCAL
19     set "var1=呵呵呵!"
20     set "%1=%var1%"
21     echo.var1 :"local Val1 %var1%"
22 ENDLOCAL
23 goto :eof

 

執行結果:

解釋: 可以看到 ,代碼中 將 var2 引用通過參數傳進去,同時在函數中將var1的變量設置為呵呵呵!,但是函數執行完后, var1,和var2都沒有變動(盡管var2是以變量的形式傳進去的),他們只有在屬於的局部區域,賦值才有效,endlocal 執行后,他們又恢復 全局變量的值了;

事件六:怎么跳過ENDLOCAL的屏障,返回局部變量值?采用”變量擴充“,在SETLOCAL與ENDLOCAL之間的全局變量的值會備份,當退出ENDLOCAL,該值將恢復。讓命令處理器來執行ENDLOCAL 和SET命令。

 1 @echo off
 2 :: 返回局部變量
 3 :: 怎么跳過ENDLOCAL的屏障,返回局部變量值?
 4 :: 采用”變量擴充“,在SETLOCAL與ENDLOCAL之間的全局變量的值會備份,當退出ENDLOCAL,該值將恢復。
 5 :: 讓命令處理器來執行ENDLOCAL 和SET命令。
 6 
 7 set "aStr=Expect no changed,Even if used in function~"
 8 set "var1=Expect changed"
 9 echo.aStr before:%aStr%
10 echo.var1 before:"%var1%"
11 call :myFunc var1
12 echo.aStr after:%aStr%
13 echo.var1 after:"%var1%"
14 pause && goto :eof
15 
16 :myFunc
17 setLocal
18 set "aStr=Try To Change!"
19 (ENDLOCAL
20     set "%1=%aStr%"
21 )
22 goto :eof

執行結果:

解釋:aStr 變量通過全局變量的形式,在 setlocal 和 endlocal 之間賦值,這個賦值肯定是不會影響外部的aStr的值的,怎樣將 這個局部設置的值保存下來?如上代碼: 在 setlocal 和 endlocal 之外 ,通過 將這個值設置給 傳進來的參數變量、或者另一個全局變量,即可將 該局部變量的賦值保存下來並返回;如上圖,var1的值變為了 局部賦值:Try To Change!;

 

事件七:編寫遞歸函數,Fibonacci函數;讓函數局部變量的變換對調用者是可見的,循環調用函數,讓變量可重用:

  

 1 @echo off
 2 :: 編寫斐波拉里 函數,用來計算多少以內的斐波拉里數! 遞歸!
 3 set "fst=0"
 4 set "fib=1"
 5 set "limit=10000"
 6 
 7 :: fib 傳的是引用, 另兩個傳的是值; fib最后用來返回值
 8 call :feberlalie fib,%fst%,%limit%
 9 echo. The next Fibonacci number greater or equal %limit% is %fib%. 
10 pause && goto :eof
11 
12 :feberlalie
13 SETLOCAL
14 
15 ::可以利用set /a 進行連續賦值,只要用逗號分開每個變量名就可以了。是下面三行代碼的縮寫
16 set /a "Num1=%1,Num2=%2,limit=%3"
17 :: set /a "Num1=%1"
18 :: set /a "Num2=%2"
19 :: set /a "limit=%3"
20 
21 :: 在set /a 計算時,可以省略變量的%號或!號,極為方便。 是帶百分號的 加法的縮寫
22 :: set /a "Sum=Num1 + Num2"
23 set /a "Sum=%Num1% + %Num2%"
24 
25 echo.Num1 :%Num1%
26 if /i %Sum% LSS %limit% call:feberlalie Sum,%Num1%,%limit%
27 (ENDLOCAL
28     IF "%1" NEQ "" SET "%1=%Sum%"
29 )
30 goto :eof

 執行結果:

 

總結:定義一個標准的dos batch script function(ps:人家總結的不錯,直接拿來用了):

 1      :myFunctionName    -- function description here  函數名
 2     ::           參數描述      -- %~1: argument description here  下面都是函數體
 3     SETLOCAL  
 4     REM.--function body here  
 5     set LocalVar1=...  
 6     set LocalVar2=...  
 7     (ENDLOCAL & REM -- RETURN VALUES  待返回的值
 8         IF "%~1" NEQ "" SET %~1=%LocalVar1%  
 9         IF "%~2" NEQ "" SET %~2=%LocalVar2%  
10     )  
11     GOTO:EOF  

 

學習參考鏈接:

http://blog.csdn.net/xiaoding133/article/details/39252357

http://www.jb51.net/article/29323.htm


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM