在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的語法呢??