99re热这里只有精品视频,7777色鬼xxxx欧美色妇,国产成人精品一区二三区在线观看,内射爽无广熟女亚洲,精品人妻av一区二区三区

4.1 環(huán)境變量延遲擴展(上)

2022-04-13 15:07 更新

《批處理入門手冊》
四. 環(huán)境變量延遲擴展(上)
-----------------------------------------------------------------------------------------------------
4.1 學習環(huán)境變量延遲擴展

學習要點:
一、什么是延遲環(huán)境變量擴展?
二、批處理變量延遲詳解

-----------------------------------------------------------------------------------------------------


一,什么是延遲環(huán)境變量擴展?

原文地址:

http://bbs.bathome.cn/thread-3083-1-1.html

延遲變量全稱"延遲環(huán)境變量擴展",要理解這個東西,我們還得先理解一下什么叫變量擴展! CMD在解釋我們的命令的時候,首先會讀取一條完整的命令,然后對其進行一些命令格式的匹配操作,看你所輸入的命令格式是不是符合它的要求.如果我們要在命令中引用一些變量,那么我們?nèi)绾巫孋MD在解釋我們的命令時,能識別出這個變量呢?這時我們就可以在變量名字兩邊加一個%號,如%name%.當CMD在讀取我們的整條命令進行格式匹配的時候,就會發(fā)現(xiàn)name這個字符兩邊加了%號,就不會把它當作普通字符處理,而是會把它當作一個變量處理,變量名叫name然后CMD就會找到變量名對應的值,用該值替換掉這個變量名字(name),(如果變量名不存在值,就返回空值).再將這個替換好并且匹配的命令執(zhí)行!這個替換值的過程,就叫做變量擴展,說白了就是把變量的名字,用它的值給替換掉后執(zhí)行!也就是批處理如何識別一個變量的過程.(注意:這里只是變量的擴展的意思,不是延遲環(huán)境變量擴展,要理解延遲環(huán)境變量擴展,必須先理解什么是變量的擴展) 也就是批處理如何識別一個變量的過程.


例1, 

@echo off
set var=test
echo %var%
pause

CMD在讀取到echo %var%這句命令后,就會進行匹配操作,它馬上就發(fā)現(xiàn)var字符兩邊有%號,這時CMD就會把它當作一 個變量處理,查看這個var變量名是不是有值,如果有就用該值把變量名var給替換掉,這里我們的var在上一條命令set var=test中,給var賦值為test,所以CMD會用test把%var%這個變量名替換掉,替換后的結(jié)果就為echo test了.這些步驟都是CMD進行匹配操作的步驟,匹配完后,他再執(zhí)行echo test這條語句,這時我們的CMD中就會echo出一個test了.什么是環(huán)境變量擴展知道了,那什么是延遲環(huán)境變量擴展呢?在理解環(huán)境變量擴展時,我們知道CMD在解釋命令時,首先會把一條完整的命令進行讀取,然后進行匹配操作,匹配時它會把命令里的變量用變量的值給替換掉,然后執(zhí)行這個替換好的命令.問題就出在"一條完整的命令",在BAT中,IF FOR這樣的命令都可以加括號,將一些命令嵌套在里面執(zhí)行.這樣的話對于一條可以加擴號嵌其他命令的命令,他的完整格式就是for %%i in (....)這樣一個整體.此時,如果我們?nèi)绻诶ㄌ柪锩媲度胍恍┰O置變量值的命令,就會出現(xiàn)問題了!


例2, 

@echo off
for /l %%i in (1,1,5) do (
    set var=%%i
    echo %var%
)
pause

執(zhí)行后會顯示5個空行的錯誤提示!為什么?根據(jù)我們上面說的知識來理解。

通過這兩個例子,大家應該已經(jīng)理解,如果只有環(huán)境變量擴展這個過程的話,如果我們在可以嵌套命令的命令中執(zhí)行 賦值操作時,會讓我們的BAT出現(xiàn)給變量賦值的問題.那么這個時候"延遲環(huán)境變量擴展",這個概念就被提出來了。在批處理中,我們可以用setloacl enabledelayedexpansion 這個命令來啟用"延遲環(huán)境變量擴展" ,在我們啟用了"延遲環(huán)境變量擴展"后,當CMD在解釋含有嵌套格式的命令時,他會把嵌套的命令一條一條的先執(zhí)行一次,然后再進行匹配操作,這樣我們的賦值操作就會完成.并且在"延遲環(huán)境變量擴展"啟用后,CMD會用!號來判斷這是不是一個變量 。如沒啟用前變量用%name%這樣的格式判斷,啟用后就用!name!這樣的格式判斷了,這個符號我們需要注意!


例3,


@echo off
setlocal enabledelayedexpansion
set var=1
for /l %%i in (1,1,5) do (
    set /a var =%%i 
    echo !var!
)
pause

這樣大家應該明白什么是延遲環(huán)境變量擴展了吧.再來一個例子


例4, 

@echo off
set var=test & echo %test%
pause


這條命令放在一行,表示他是一條完整的命令,不啟用"延遲環(huán)境變量擴展",就會出現(xiàn)上面的賦值錯誤!改成下這樣就 OK了:

@echo off
setlocal enabledelayedexpansion
set var=test & echo !var!
pause

-----------------------------------------------------------------------------------------------------

 


二,批處理變量延遲詳解

原文地址:

http://bbs.bathome.cn/viewthread.php?tid=2898

關于環(huán)境變量延遲擴展,使用set /?可以查看到部分說明,不過考慮到其粗劣的翻譯水平,建議在查看之前,首先chcp 437切換為英文查看原英文說明。鑒于文中已說得十分詳盡,而且有數(shù)個代碼示例,應該不難理解。在此僅略作一些補充。


在許多可見的官方文檔中,均將使用一對百分號閉合環(huán)境變量以完成對其值的替換行為稱之為“擴展(expansion )”,這其實是一個第一方的概念,是從命令解釋器的角度進行稱謂的,而從我們使用者的角度來看,則可以將它看作是引用(Reference)、調(diào)用(Call)或者獲?。℅et)。


而命令解釋器是擴展環(huán)境變量的行為大致如下:首先讀取命令行的一條完整語句,在進行一些先期的預處理之后,命令被解釋執(zhí)行之前,會對其中用百分號閉合的字符串進行匹配,如果在環(huán)境空間中找到了與字符串相匹配的環(huán)境變量,則用其值替換掉原字符串及百分號本身,如果未得到匹配,則用一個空串替換,這個過程就是環(huán)境變量的“擴展”,它仍然屬于命令行的預處理范疇。


而一條“完整的語句”,在NT的命令解釋器CMD中被解釋為“for if else”等含有語句塊的語句和用“& | && ||”等連接起來的復合語句。

因此,當CMD讀取for語句時,其后用一對圓擴號閉合的所有語句將一同讀取,并完成必要的預處理工作,這其中就包括環(huán)境變量的擴展,所以在for中的所有語句執(zhí)行之前,所有的環(huán)境變量都已經(jīng)被替換為for之前所設定的值,從而成為一個字符串常量,而不再是變量。無論在for中將那些環(huán)境變量如何修改,真正受到影響的只是環(huán)境變量空間,而非for語句內(nèi)部。


而為了能夠在for語句內(nèi)部感知環(huán)境變量的動態(tài)變化,CMD設計了延遲的環(huán)境變量擴展特性,也就是說,當CMD讀取了一條完整的語句之后,它不會立即執(zhí)行變量的擴展行為,而會在某個單條語句執(zhí)行之前再進行擴展,也就是說,這個擴展行為被“延遲”了。


延遲環(huán)境變量擴展特性在CMD中缺省是關閉的,開啟它的方法目前有兩個:一是CMD /v:off(此處說法有誤,應為 CMD /v:on——namejm 注),它會打開一個新的命令行外殼,在使用exit退出這個外殼之前,擴展特性始終有效,常用于命令行環(huán)境中;二是setlocal EnableDelayedExpansion,它會使環(huán)境變量的修改限制到局部空間中,在endlocal之后,擴展特性和之前對環(huán)境變量的修改將一同消失,常用于批處理語句中。(原貼詳見:http://www.cn-dos.net/forum/viewthread.php?tid=28273)


上面是willsort寫的帖子對于新手來說比較難理解。不過沒關系,我們先分析一個例子,同樣是引用willsort老大的。


本例啟用了變量延遲,是個正確的例子!


例1, 

@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雙擊執(zhí)行后會顯示“Will Sort”字符串,下面將講解每個語句的意思:

1.@echo off & setlocal EnableDelayedExpansion
關閉命令回顯,并啟用變量延遲

2.for /f  "tokens=* delims=" %%i in ("Hello world.") do (  )
for命令及其參數(shù)的使用,請大家在論壇里搜索相關字眼。限于篇幅問題,這里不作討論。如果此時你不明白它的意思,那么你就當它的作用是把字符串“Hello world.”賦值給%%i好了,當然這只是權宜之計,以后一定要學習for的使用!

3.set n=%%i
把%%i的值(即Hello world.)賦予給變量n,這個大家都知道吧

4.set n=!n:ld.=t!
這里要講講set替換字符的功能了。這個語句的意思是,先獲取變量n的值(此時n的值是“Hello world.”),然后將字符“t”替換字符“l(fā)d.”,然后再將替換后的結(jié)果再次賦值給變量n(此時n的值變?yōu)椤癏ello wort”)。至于set替換字符的編寫格式,大家可以在CMD鍵入“set/?”找到“%PATH:str1=str2%”這段有說明

5.set n=!n:o w= S!
意思和上句一樣,只是替換和被替換的內(nèi)容不同。它是將“ S”替換“o w”(注意S前面和w前面都有個空格),其實willsort老大是想證明set替換字符是支持句點和空格的(第4句“l(fā)d”后面有個.)。此時n的值為“Hell Sort”


6.set n=!n:He=Wi!
這句不用說了吧,執(zhí)行完這句后n的值為“Will Sort”


7.echo !n!
顯示變量n的值

需要注意的是,一旦啟用了變量延遲,就要用!號把變量括起來,而不能用%號。

  好了,每句的意思已經(jīng)說完了,下面要講本帖真正要討論的變量延遲的問題。
這里又要引用Will Sort老大的說明:當CMD讀取for語句時,其后用一對圓括號閉合的所有語句將一同讀取,并完成
必要的預處理工作,這其中就包括環(huán)境變量的擴展,所以在for中的所有語句執(zhí)行之前,所有的環(huán)境變量都已經(jīng)被替
換為for之前所設定的值,從而成為一個字符串常量,而不再是變量。

  而為了能夠在for語句內(nèi)部感知環(huán)境變量的動態(tài)變化,CMD設計了延遲的環(huán)境變量擴展特性,也就是說,當CMD讀取
了一條完整的語句之后,它不會立即執(zhí)行變量的擴展行為,而會在某個單條語句執(zhí)行之前再進行擴展,也就是說,這
個擴展行為被“延遲”了。

  總的來說是,在沒有啟用變量延遲的情況下,凡是在括號內(nèi)(即do里面)的變量,在執(zhí)行for語句之前,就已經(jīng)被
替換成for語句之前其它命令對該變量所賦予的值。這句話不懂沒關系,下面再看一個例子,看完你就會明白。


例2, 

@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

  這和前面的例子差不多,只是所有!號都換成%號,這是個錯誤的例子。因為它沒有啟用變量延遲,也沒有使用!
號把變量括起來。我們看到它的執(zhí)行結(jié)果是顯示“ECHO 處于關閉狀態(tài)”。
為什么會這樣呢?原因是,在沒有啟用變量延遲的情況下,凡是在括號內(nèi)(即do里面)的變量,在執(zhí)行for語句之前
,就已經(jīng)被替換成for語句之前其它命令對該變量所賦予的值。

則是說在本例中的以下幾句


set n=%%i
set n=%n:ld.=t%
set n=%n:o w= S%
set n=%n:He=Wi%
echo %n%

  第一句能正常執(zhí)行并達到它的目的,因為它只是單純地將%%i的值賦予給變量n,所以沒有任何問題。其它幾句屬
這樣情況:早在for語句執(zhí)行前,CMD就急不切待地將這幾句里面的所有變量n一同執(zhí)行替換行為,替換為for之前,
其它命令對n所設置的值,從而使n變成一個常量。但在本例中,for語句之前只有@echo off這句,并沒有其它命令
對n作過任何賦值行為,所以在for之前,變量n的值為空值。
  即是說,set n=%n:ld.=t% 這句里面的變量n,在CMD讀?。ㄗ⒁馐亲x取不是執(zhí)行)完整個for語句后(這時還未輪
到set執(zhí)行自己的任務),就立刻被替換為一個空值,一個空值里面沒有任何東西,所以就不存在一字符替換另一字
符這種說法(沒有東西怎么替換?)。最終到執(zhí)行set n=%n:ld.=t%語句時,它只是獲取一個空值,再給變量n賦予
空值而已。其它幾句也是一樣原理。

  所以,最后echo %n%的時候變量n還是個空值,而echo命令沒有東西可以顯示,就只有顯示“ECHO 處于關閉狀態(tài)
”這句來說明自己的狀態(tài)

通過這個例子的說明,相信大家已經(jīng)知道變量延遲的作用吧!我們再回頭來看看例1。

啟用變量延遲后,在執(zhí)行


set n=!n:ld.=t!
set n=!n:o w= S!
set n=!n:He=Wi!
echo !n!

這些語句前,它們里面的變量n不會馬上被CMD替換(啟用延遲后,CMD變得有耐性啦^_^),而未被替換的話,那么n
就還是變量,而不是常量。等到執(zhí)行set n=!n:ld.=t!等這幾句時,變量n才被替換。這樣每個set命令都能感知變量
n的任何變化,從而作出正確的替換行為。這就是變量延遲啦!

不要以為只有for才要用變量延遲,下面這個例子同樣需要

例3,這是個錯誤的例子


@echo off
set mm=girl&echo %mm%
pause

執(zhí)行后依然顯示“ECHO 處于關閉狀態(tài)”。

  原因是沒有啟用延遲,而且在set mm=girl&echo %mm%語句前沒有其它命令對mm進行賦值。這時當CMD執(zhí)行set
mm=girl&echo %mm%語句前,就已經(jīng)急不切待地把變量mm的值替換了,而又因為前面沒給mm賦值,所以mm被替換為空
值,變成常量。等到echo命令執(zhí)行時,它其實是echo一個不會變化的常量,本例中即是空值。

有人會問,echo前面不是給mm賦值了嗎?
這個就要關系到CMD解釋命令的步驟,大家可以參詳本帖開頭willsort的帖子。

  總的來說是,如果不啟用變量延遲,在本例中,echo是不會理會也不會知道,它前面(指同一行語句)是否有其
它命令給mm賦值。它只會從set mm=girl&echo %mm%這句以上的語句中獲取它所要顯示的變量的內(nèi)容,也就是說,上
一行或上幾行的命令將mm設置成什么值,echo命令就顯示什么值。

大家這樣做就明白了:


@echo off
set mm=boy
set mm=girl&echo %mm%
pause

看看顯示什么結(jié)果就知道了!

這樣編寫例3才正確:


@echo off&setlocal EnableDelayedExpansion
set mm=girl&echo !mm!
pause

開啟了變量延遲,變量擴展(替換)的行為就推遲到echo命令執(zhí)行時,這時echo能感知它前面的命令(本例的set)
對變量mm做了什么“壞事”,從而作出正確的判斷并執(zhí)行
-----------------------------------------------------------------------------------------------------

 


注:以上文章在編輯整理時稍有修改!
Januapr編輯于2009-09-15 星期二14:32:57.46


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號