2010年5月25日 星期二

SETLOCAL指令

在bat檔中,常常會遇到在IF或是FOR裡面做完運算之後,
直接在下一行確沒有辦法讀到上一行的結果~

例如:

@echo off
set Val=1
echo %Val%
(
set Val=2
echo %Val%
set Val=3
echo %Val%
)
echo %Val%
pause


我哩!我明明有在裡面變更Val的值,都是為啥印出來確都沒有變哩~
而是只有執行到括號的結束之後,整個值才有變。
那這樣有啥用啊~

今天在網路上,不小心看到一個新指令SETLOCAL

說明如下:
SETLOCAL 批次命令現在可接受一個選項引數,這個引數可為:
ENABLEEXTENSIONS / DISABLEEXTENSIONS
啟用或停用命令處理擴充功能。
請用 CMD /? 來查看說明。
ENABLEDELAYEDEXPANSION / DISABLEDELAYEDEXPANSION
啟用或停用延遲環境變數擴充功能。
請用 SET /? 來查看說明。
這些修正命令作用會持續到對應 ENDLOCAL 命令為止,而不管
它們的設定是否在 SETLOCAL 命令之前。


範例程式如下:
@echo off
SETLOCAL ENABLEDELAYEDEXPANSION
set Val=1
echo %Val% !Val!
(
set Val=2
echo %Val% !Val!
set Val=3
echo %Val% !Val!
)
echo %Val% !Val!
pause

輸出結果如下:
1 1
1 2
1 3
3 3
請按任意鍵繼續 . . .


喔耶,這樣就可以在IF或是FOR做運算的動作,同時,也可以在括號裡面做判斷啦~

批次檔 有沒有類似 IF...THEN....ELSE 跟 OR的語法呢??
以上聯結的重點
在 %xxx% 的使用是在 執行 指令時...將 %xxx% 的 值 取代(展開) %xxx% 到指令句中
而在 if for 和 ( ) 指令 執行 時...這扯到指令處理的方式
在我寫的範疇中... 在處理 ( ) 時... 是將 ( ) 其中的指令一起處理
因此 ( ) 中在實際執行時...就把 %Val% 取代了... 而執行 ( ) 之前 Val 是 =1
set Val=1
(
set Val=2
echo 1 !Val!
set Val=3
echo 1 !Val!
)

即 ( ) 是將 %Val% 一次 展開
所以 !xxx! 的意思和 %xxx% 不一樣
!xxx! 是使用時 (該指令執行時) 才取代(展開)
這就是 "延遲"環境變數展開功能

簡單說就是 %xxxx% !xxxx! 展開 的 時間點 不同

( ) 是 CMD 本身的 指令區段 的寫法
而 if for 使用時也是有 指令區段 ...只不過如果只有一行...可以省略不打 ( ) 而以
不過也是要看情況...例如 if
if "a"=="b" echo 1
等於
if "a"=="b" (echo 1)

if "a"=="b" echo 1 else echo 2
等於
if "a"=="b" (echo 1 else echo 2)
所以正常要用 else 要打成
if "a"=="b" (echo 1) else (echo 2)

而基本上...每行指令...本身就有一個指令區段

set a=1
set a=2&echo %a%



結果是顯示 1
因為實際上等於是
(set a=1)
(set a=2&echo %a%)
而這等同
(set a=1)
(
set a=2
echo %a%
)

也就是 ( ) 視為一個指令(指令區段)
而 %xxxx% 展開 是在 執行 指令(指令區段) 時就先展開
而 !xxxx! 是在執行 指令區段 中的 單行指令 時才展開

參考資料:
批次檔 有沒有類似 IF...THEN....ELSE 跟 OR的語法呢??

沒有留言: