天天看點

【DOS批處理】函數定義和用法

本文主要講述如下幾個問題:

   1.什麼是函數,怎麼建立函數?

   2.怎麼調用一個函數?

   3.函數是怎麼工作的?

   4.怎麼向函數傳遞參數?

   5.函數怎麼傳回值和傳回一個局部變量的值。

一、建立函數(什麼是函數)

在batch script 中的函數以一個标簽開始,并以goto:eof結束,如下:

 script

1. :myDosFunc    - 函數的開始,用一個标簽辨別  
2. echo. 函數體,可以執行很多指令  
3. echo.   
4. GOTO:EOF      

二、調用函數

Script: 01.

 call:myDosFunc

三、函數怎麼工作

  調用函數的腳本将其分成兩部分。

    1.main script: 從第一行開始并且以 GOTO:EOF指令結束

    2.函數部分:由多個函數組成,由main script調用。

   SCRIPT:

1. @echo off  
2. echo.開始調用函數  
3. call:myDosFunc  
4. echo.從函數傳回myDosFunc  
5. echo.&pause&goto:eof  
6. ::--------------------------------------------------------  
7. ::-- 函數部分開始  
8. ::--------------------------------------------------------  
9. :myDosFunc    - here starts my function identified by it`s label  
10. echo.  here the myDosFunc function is executing a group of commands  
11. echo.  it could do a lot of things  
12. goto:eof      

三、怎麼傳遞參數,并且在函數中擷取參數的值

   1.用空格或者逗号将參數分開

   2.用雙引号将帶有空格的字元串參數括起來

1. call:myDosFunc 100 YeePEE  
2. call:myDosFunc 100 "for me"  
3. call:myDosFunc 100,"for me"      

   擷取參數,采用%1~%9來擷取每個參數的值。%0,表示批處理檔案本身

1.  :myDosFunc    - here starts myDosFunc identified by it`s label  
2. echo.  
3. echo. here the myDosFunc function is executing a group of commands  
4. echo. it could do %~1 of things %~2.  
5. goto:eof      

 帶參數的腳本

1.  @echo off  
2. echo.going to execute myDosFunc with different arguments  
3. call:myDosFunc 100 YeePEE  
4. call:myDosFunc 100 "for me"  
5. call:myDosFunc 100,"for me"  
6. call:myDosFunc 100,for me  
7. echo.&pause&goto:eof  
8. ::--------------------------------------------------------  
9. ::-- Function section starts below here  
10. ::--------------------------------------------------------  
11. :myDosFunc    - here starts my function identified by it's label  
12. echo.  
13. echo. here the myDosFunc function is executing a group of commands  
14. echo. it could do %~1 of things %~2.  
15. goto:eof      

四、函數傳回值

   1、調用指令不像其他語言那樣能有傳回值,最常用的做法是在函數中将該值儲存在全局變量中,調用結束後

直接用該全局變量。如下:

  Usage:

1.  set "var1=some hopefully not important string"  
2. echo.var1 before: %var1%  
3. call:myGetFunc  
4. echo.var1 after : %var1%      

Script:

1.  :myGetFunc    - get a value  
2. set "var1=DosTips"  
3. goto:eof      

腳本輸出如下:

var1 before: some hopefully not important string

var1 after : DosTips

  2、通過引用傳回值,調用者通過傳遞一個變量給函數來存儲傳回值

Usage:

1. call:myGetFunc var1  
2. cho.var1 after : %var1%      

Script:

1.  :myGetFunc    - passing a variable by reference  
2. set "%~1=DosTips"  
3. goto:eof      

腳本輸出如下:

var1 after : DosTips

完整腳本:

1.  @echo off  
2. set "var1=CmdTips"  
3. echo.var1 before: %var1%  
4. call:myGetFunc var1  
5. echo.var1 after : %var1%  
6. echo.&pause&goto:eof  
7.   
8. ::--------------------------------------------------------  
9. ::-- Function section starts below here  
10. ::--------------------------------------------------------  
11. :myGetFunc    - passing a variable by reference  
12. set "%~1=DosTips"  
13. goto:eof      

五、函數的局部變量

   怎麼保證局部變量和全局變量不沖突,SETLOCAL指令能讓處理器當做是局部變量,用ENDLOCAL解除局部變量。

ENDLOCAL 會被自動調用,當批處理執行到檔案末尾的時候,即GOTO:EOF。SETLOCAL可以很好的保護函數内與外面的變量不會沖突。

1.  @echo off  
2. set "aStr=Expect no changed, even if used in function"  
3. set "var1=No change for this one.  Now what?"  
4. echo.aStr before: %aStr%  
5. echo.var1 before: %var1%  
6. call:myGetFunc var1  
7. echo.aStr after : %aStr%  
8. echo.var1 after : %var1%  
9. echo.&pause&goto:eof  
10. ::--------------------------------------------------------  
11. ::-- Function section starts below here  
12. ::--------------------------------------------------------  
13. :myGetFunc    - passing a variable by reference  
14. SETLOCAL  
15. set "aStr=DosTips"  
16. set "%~1=%aStr%"  
17. ENDLOCAL  
18. goto:eof      

腳本輸出:

aStr before: Expect no changed, even if used in function

var1 before: No change for this one.  Now what?

aStr after : Expect no changed, even if used in function

var1 after : No change for this one.  Now what?

   傳回局部變量

      ----怎麼跳過ENDLOCAL的屏障,傳回局部變量值?

   采用”變量擴充“,在SETLOCAL與ENDLOCAL之間的全局變量的值會備份,當退出ENDLOCAL,該值将恢複。讓指令處理器來執行ENDLOCAL 和SET指令。

1.  @echo off  
2. set "aStr=Expect no changed, even if used in function"  
3. set "var1=Expect changed"  
4. echo.aStr before: %aStr%  
5. echo.var1 before: %var1%  
6. call:myGetFunc var1  
7. echo.aStr after : %aStr%  
8. echo.var1 after : %var1%  
9. echo.&pause&goto:eof  
10. ::--------------------------------------------------------  
11. ::-- Function section starts below here  
12. ::--------------------------------------------------------  
13. :myGetFunc    - passing a variable by reference  
14. SETLOCAL  
15. set "aStr=DosTips"  
16. ( ENDLOCAL  
17.     set "%~1=%aStr%"  
18. )  
19. goto:eof  
20. :myGetFunc2    - passing a variable by reference  
21. SETLOCAL  
22. set "aStr=DosTips"  
23. ENDLOCAL&set "%~1=%aStr%"       &rem THIS ALSO WORKS FINE  
24. goto:eof      

腳本輸出:

aStr before: Expect no changed, even if used in function

var1 before: Expect changed

aStr after : Expect no changed, even if used in function

var1 after : DosTips

六、編寫遞歸函數

     讓函數局部變量的變換對調用者是可見的,循環調用函數,讓變量可重用。下面編寫一個函數計算Fibonacci數列。

1.  @echo off  
2. set "fst=0"  
3. set "fib=1"  
4. set "limit=1000000000"  
5. call:myFibo fib,%fst%,%limit%  
6. echo.The next Fibonacci number greater or equal %limit% is %fib%.  
7. echo.&pause&goto:eof  
8.   
9. ::--------------------------------------------------------  
10. ::-- Function section starts below here  
11. ::--------------------------------------------------------  
12. :myFibo  -- calculate recursively the next Fibonacci number greater or equal to a limit  
13. ::       -- %~1: return variable reference and current Fibonacci number  
14. ::       -- %~2: previous value  
15. ::       -- %~3: limit  
16. SETLOCAL  
17. set /a "Number1=%~1"  
18. set /a "Number2=%~2"  
19. set /a "Limit=%~3"  
20. set /a "NumberN=Number1 + Number2"  
21. if /i %NumberN% LSS %Limit% call:myFibo NumberN,%Number1%,%Limit%  
22. (ENDLOCAL  
23.     IF "%~1" NEQ "" SET "%~1=%NumberN%"  
24. )  
25. goto:eof      

七、總結,定義一個标準的dos batch script function

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