?? 變量延遲詳解(新手推薦).txt
字號:
willsort老大上面的帖子,對于新手來說比較難理解。不過沒關系,我們先分析一個例子,同樣是引用willsort老大的。本例啟用了變量延遲,是個正確的例子!
例1:
CODE: [Copy to clipboard]
--------------------------------------------------------------------------------
@echo off & setlocal EnableDelayedExpansion
for /f "tokens=* delims=" %%i in ("Hello world.") do (
set n=%%i
set n=!n:ld.=t!
set n=!n:o w= S!
set n=!n:He=Wi!
echo !n!
)
pause
將上面代碼保存為.bat雙擊執行后會顯示“Will Sort”字符串,下面將講解每個語句的意思:
1.@echo off & setlocal EnableDelayedExpansion
關閉命令回顯,并啟用變量延遲
2.for /f "tokens=* delims=" %%i in ("Hello world.") do (
for命令及其參數的使用,請大家在論壇里搜索相關字眼。限于篇幅問題,這里不作討論。如果此時你不明白它的意思,那么你就當它的作用是把字符串“Hello world.”賦值給%%i好了,當然這只是權宜之計,以后一定要學習for的使用!
3.set n=%%i
把%%i的值(即Hello world.)賦予給變量n,這個大家都知道吧
4.set n=!n:ld.=t!
這里要講講set替換字符的功能了。這個語句的意思是,先獲取變量n的值(此時n的值是“Hello world.”),然后將字符“t”替換字符“ld.”,然后再將替換后的結果再次賦值給變量n(此時n的值變為“Hello wort”)。至于set替換字符的編寫格式,大家可以在CMD鍵入“set/?”找到“%PATH:str1=str2%”這段有說明
5.set n=!n:o w= S!
意思和上句一樣,只是替換和被替換的內容不同。它是將“ S”替換為“o w”(注意S前面和w前面都有個空格),其實willsort老大是想證明set替換字符是支持句點和空格的(第4句“ld”后面有個.)。此時n的值為“Hell Sort”
6.set n=!n:He=Wi!
這句不用說了吧,執行完這句后n的值為“Will Sort”
7.echo !n!
顯示變量n的值
需要注意的是,一旦啟用了變量延遲,就要用!號把變量括起來,而不能用%號。
好了,每句的意思已經說完了,下面要講本帖真正要討論的變量延遲的問題。
這里又要引用Will Sort老大的說明:當CMD讀取for語句時,其后用一對圓括號閉合的所有語句將一同讀取,并完成必要的預處理工作,這其中就包括環境變量的擴展,所以在for中的所有語句執行之前,所有的環境變量都已經被替換為for之前所設定的值,從而成為一個字符串常量,而不再是變量。
而為了能夠在for語句內部感知環境變量的動態變化,CMD設計了延遲的環境變量擴展特性,也就是說,當CMD讀取了一條完整的語句之后,它不會立即執行變量的擴展行為,而會在某個單條語句執行之前再進行擴展,也就是說,這個擴展行為被“延遲”了。
總的來說是,在沒有啟用變量延遲的情況下,凡是在括號內(即do里面)的變量,在執行for語句之前,就已經被替換成for語句之前其它命令對該變量所賦予的值。這句話不懂沒關系,下面再看一個例子,看完你就會明白。
例2:
CODE: [Copy to clipboard]
--------------------------------------------------------------------------------
@echo off
for /f "tokens=* delims=" %%i in ("Hello world.") do (
set n=%%i
set n=%n:ld.=t%
set n=%n:o w= S%
set n=%n:He=Wi%
echo %n%
)
pause
這和前面的例子差不多,只是所有!號都換成%號,這是個錯誤的例子。因為它沒有啟用變量延遲,也沒有使用!號把變量括起來。我們看到它的執行結果是顯示“ECHO 處于關閉狀態”。
為什么會這樣呢?原因是,在沒有啟用變量延遲的情況下,凡是在括號內(即do里面)的變量,在執行for語句之前,就已經被替換成for語句之前其它命令對該變量所賦予的值。
則是說在本例中的以下幾句
set n=%%i
set n=%n:ld.=t%
set n=%n:o w= S%
set n=%n:He=Wi%
echo %n%
第一句能正常執行并達到它的目的,因為它只是單純地將%%i的值賦予給變量n,所以沒有任何問題。其它幾句屬這樣情況:早在for語句執行前,CMD就急不切待地將這幾句里面的所有變量n一同執行替換行為,替換為for之前,其它命令對n所設置的值,從而使n變成一個常量。但在本例中,for語句之前只有@echo off這句,并沒有其它命令對n作過任何賦值行為,所以在for之前,變量n的值為空值。即是說,set n=%n:ld.=t% 這句里面的變量n,在CMD讀取(注意是讀取不是執行)完整個for語句后(這時還未輪到set執行自己的任務),就立刻被替換為一個空值,一個空值里面沒有任何東西,所以就不存在一字符替換另一字符這種說法(沒有東西怎么替換?)。最終到執行set n=%n:ld.=t%語句時,它只是獲取一個空值,再給變量n賦予空值而已。其它幾句也是一樣原理。
所以,最后echo %n%的時候變量n還是個空值,而echo命令沒有東西可以顯示,就只有顯示“ECHO 處于關閉狀態”這句來說明自己的狀態
通過這個例子的說明,相信大家已經知道變量延遲的作用吧!我們再回頭來看看例1。
啟用變量延遲后,在執行
set n=!n:ld.=t!
set n=!n:o w= S!
set n=!n:He=Wi!
echo !n!
這些語句前,它們里面的變量n不會馬上被CMD替換(啟用延遲后,CMD變得有耐性啦^_^),而未被替換的話,那么n就還是變量,而不是常量。等到執行set n=!n:ld.=t!等這幾句時,變量n才被替換。這樣每個set命令都能感知變量n的任何變化,從而作出正確的替換行為。這就是變量延遲啦!
可跳過:
什么,說我講得不好?沒辦法啊,因為偶太菜啊,只知道這些。偶只是淘兩頓飯吃而已,望大家諒解啊,不要再拿磚頭砸偶。。。不然偶就~~~~~~~~~~叫救命!^_^
這是正文不可跳過:
不要以為只有for才要用變量延遲,下面這個例子同樣需要
例3:這是個錯誤的例子
CODE: [Copy to clipboard]
--------------------------------------------------------------------------------
@echo off
set mm=girl&echo %mm%
pause
執行后依然顯示“ECHO 處于關閉狀態”。
原因是沒有啟用延遲,而且在set mm=girl&echo %mm%語句前沒有其它命令對mm進行賦值。這時當CMD執行set mm=girl&echo %mm%語句前,就已經急不切待地把變量mm的值替換了,而又因為前面沒給mm賦值,所以mm被替換為空值,變成常量。等到echo命令執行時,它其實是echo一個不會變化的常量,本例中即是空值。
有人會問,echo前面不是給mm賦值了嗎?
這個就要關系到CMD解釋命令的步驟,大家可以參詳本帖開頭willsort的帖子。
總的來說是,如果不啟用變量延遲,在本例中,echo是不會理會也不會知道,它前面(指同一行語句)是否有其它命令給mm賦值。它只會從set mm=girl&echo %mm%這句以上的語句中獲取它所要顯示的變量的內容,也就是說,上一行或上幾行的命令將mm設置成什么值,echo命令就顯示什么值。
大家這樣做就明白了:
CODE: [Copy to clipboard]
--------------------------------------------------------------------------------
@echo off
set mm=boy
set mm=girl&echo %mm%
pause
看看顯示什么結果就知道了!
這樣編寫例3才正確:
CODE: [Copy to clipboard]
--------------------------------------------------------------------------------
@echo off&setlocal EnableDelayedExpansion
set mm=girl&echo !mm!
pause
開啟了變量延遲,變量擴展(替換)的行為就推遲到echo命令執行時,這時echo能感知它前面的命令(本例的set)對變量mm做了什么“壞事”,從而作出正確的判斷并執行
好了全篇完了,下課!
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -