主頁(yè) > 知識(shí)庫(kù) > 變量延遲詳解 call setlocal

變量延遲詳解 call setlocal

熱門標(biāo)簽:菏澤電銷外呼系統(tǒng)軟件 南陽(yáng)高頻外呼系統(tǒng)怎么安裝 外呼系統(tǒng)解決電銷問題 貴陽(yáng)電話外呼系統(tǒng)廠家 地圖標(biāo)注店鋪的收費(fèi) 京東辦理400電話查詢 為什么申請(qǐng)400電話 高德百度地圖標(biāo)注推廣 蘇丹地圖標(biāo)注app

對(duì)于批處理新手而言,“變量延遲”這個(gè)概念很可能聞所未聞,但是,它卻像一堵橫亙?cè)谀闱斑M(jìn)道路上的無形高墻,你感受不到它的存在,但當(dāng)你試圖往前沖時(shí),它會(huì)把你狠狠地彈回來,讓你無法逾越、無功而返;而一旦找到了越過它的方法,你就會(huì)發(fā)現(xiàn),在for的世界里,前面已經(jīng)是一片坦途,而你對(duì)批處理的理解,又上升到了一個(gè)新的境界。

  例如,你編寫了這樣一個(gè)代碼:

@echo off
set num=0echo %num%
pause

你的本意是想對(duì)變量num賦值之后,再把這個(gè)值顯示出來,結(jié)果,顯示出來的并不是0,而是顯示:ECHO 處于關(guān)閉狀態(tài)。

  之所以會(huì)出錯(cuò),是因?yàn)椤白兞垦舆t”這個(gè)家伙在作怪。

  在講解變量延遲之前,我們需要了解一下批處理的執(zhí)行過程,它將有助于我們深入理解變量延遲。

  批處理的執(zhí)行過程是怎樣的呢?

  “自上而下,逐條執(zhí)行”,我想,這個(gè)經(jīng)典的說法大家都已經(jīng)耳熟能詳了,沒事的時(shí)候倒著念,也還別有一番古韻呢^_^,但是,我想問大家的是,大家真的深刻地理解了這句話的含義了嗎?

  “自上而下”,這一條和我們本節(jié)的講解關(guān)系不大,暫時(shí)略過不說,后一條,“逐條執(zhí)行”和變量延遲有著莫大的干系,它是我們本節(jié)要關(guān)注的重點(diǎn)。

  很多人往往認(rèn)為一行代碼就是一條語句,從而把“逐條執(zhí)行”與“逐行執(zhí)行”等同起來,這就大錯(cuò)特錯(cuò)了。

  莫非“逐條執(zhí)行”里暗藏著玄機(jī)?

  正是如此。

  “逐條”并不等同于“逐行”。這個(gè)“條”,是“一條完整的語句”的意思,并不是指“一行代碼”。在批處理中,是不是一條完整的語句,并不是以行來論的,而是要看它的作用范圍。

  什么樣的語句才算“一條完整的語句”呢?

  1、在復(fù)合語句中,整個(gè)復(fù)合語句是一條完整的語句,而無論這個(gè)復(fù)合語句占用了多少行的位置。常見的復(fù)合語句有:for語句、if……else語句、用連接符、||和連接的語句,用管道符號(hào)|連接的語句,以及用括號(hào)括起來的、由多條語句組合而成的語句塊;
  2、在非復(fù)合語句中,如果該語句占據(jù)了一行的位置,則該行代碼為一條完整的語句。
  例如:

@echo off
set num=0
for /f %%i in ('dir /a-d /b *.exe') do (
set /a num+=1
echo num 當(dāng)前的值是 %num%
)
echo 當(dāng)前目錄下共有 %num% 個(gè)exe文件
dir /a-d /b *.txt|findstr "test">nul(
echo 存在含有 test 字符串的文本本件
)||echo 不存在含有 test 字符串的文本文件
if exist test.ini (
echo 存在 test.ini 文件
) else echo 不存在 test.ini 文件
pause

上面的代碼共有14行,但是只有完整的語句只有7條,它們分別是:

  第1條:第1行的echo語句;
  第2條:第2行的set語句;
  第3條:第3、4、5、6行上的for復(fù)合語句;
  第4條:第7行的echo語句;
  第5條:第8、9、10行上用和||連接的復(fù)合語句;
  第6條:第11、12、13行上的if……else復(fù)合語句;
  第7條:第14行上的pause語句。

  在這里,我之所以要花這么長(zhǎng)的篇幅來說明一行代碼并不見得就是一條語句,是因?yàn)榕幚淼膱?zhí)行特點(diǎn)是“逐條”執(zhí)行而不是“逐行”執(zhí)行,澄清了這個(gè)誤解,將會(huì)更加理解批處理的預(yù)處理機(jī)制。

  在代碼“逐條”執(zhí)行的過程中,cmd.exe這個(gè)批處理解釋器會(huì)對(duì)每條語句做一些預(yù)處理工作,這就是批處理中大名鼎鼎的“預(yù)處理機(jī)制”。

  預(yù)處理的大致情形是這樣的:首先,把一條完整的語句讀入內(nèi)存中(不管這條語句有多少行,它們都會(huì)被一起讀入),然后,識(shí)別出哪些部分是命令關(guān)鍵字,哪些是開關(guān)、哪些是參數(shù),哪些是變量引用……如果代碼語法有誤,則給出錯(cuò)誤提示或退出批處理環(huán)境;如果順利通過,接下來,就把該條語句中所有被引用的變量及變量?jī)蛇叺陌俜痔?hào)對(duì),用這條語句被讀入內(nèi)存之就已經(jīng)賦予該變量的具體值來替換……當(dāng)所有的預(yù)處理工作完成之后,批處理才會(huì)執(zhí)行每條完整語句內(nèi)部每個(gè)命令的原有功能。也就是說,如果命令語句中含有變量引用(變量及緊鄰它左右的百分號(hào)對(duì)),并且某個(gè)變量的值在命令的執(zhí)行過程中被改變了,即使該條語句內(nèi)部的其他地方也用到了這個(gè)變量,也不會(huì)用最新的值去替換它們,因?yàn)槟硹l語句在被預(yù)處理的時(shí)候,所有的變量引用都已經(jīng)被替換成字符串常量了,變量值在復(fù)合語句內(nèi)部被改變,不會(huì)影響到語句內(nèi)部的其他任何地方。

  順便說一下,運(yùn)行代碼[code20]之后,將在屏幕上顯示當(dāng)前目錄下有多少個(gè)exe文件,是否存在含有 test 字符串的文本文件,以及是否存在 test.ini 這個(gè)文件等信息。讓很多人百思不得其解的是:如果當(dāng)前目錄下存在exe文件,那么,有多少個(gè)exe文件,屏幕上就會(huì)提示多少次 "num 當(dāng)前的值是 0" ,而不是顯示1到N(N是exe文件的個(gè)數(shù))。

  結(jié)合上面兩個(gè)例子,我們?cè)賮矸治鲆幌拢瑸槭裁催@兩段代碼的執(zhí)行結(jié)果和我們的期望有一些差距。

  在[code19]中,set num=0echo %num%是一條復(fù)合語句,它的含義是:把0賦予變量num,成功后,顯示變量num的值。

  雖然是在變量num被賦值成功后才顯示變量num的值,但是,因?yàn)檫@是一條復(fù)合語句,在預(yù)處理的時(shí)候,后的%num%只能被set語句之前的語句賦予變量num的具體值來替換,而不能被復(fù)合語句內(nèi)部、之前的set語句對(duì)num所賦予的值來替換,可見,此num非彼num??墒牵谶@條復(fù)合語句之前,我們并沒有對(duì)變量num賦值,所以,之后的%num%是空值,相當(dāng)于在之后只執(zhí)行了 echo 這一命令,所以,會(huì)顯示 echo 命令的當(dāng)前狀態(tài),而不是顯示變量num的值(雖然該變量的值被set語句改變了)。

  在[code20]中,for語句的含義是:列舉當(dāng)前目錄下的exe文件,每發(fā)現(xiàn)一個(gè)exe文件,變量num的值就累加1,并顯示變量num的值。

  看了對(duì)[code19]的分析之后,再來分析[code20]就不再那么困難了:第3、4、5行上的代碼共同構(gòu)成了一條完整的for語句,而語句"echo num 當(dāng)前的值是 %num%"與"set /a num+=1"同處復(fù)合語句for的內(nèi)部,那么,第4行上set改變了num的值之后,并不能對(duì)第5行上的變量num有任何影響,因?yàn)樵陬A(yù)處理階段,第5行上的變量引用%num%已經(jīng)被在for之前就賦予變量num的具體值替換掉了,它被替換成了0(是被第2行上的set語句賦予的)。

  如果想讓代碼[code19]的執(zhí)行結(jié)果中顯示之前賦予num的值,讓代碼[code20]在列舉exe文件的時(shí)候,從1到N地顯示exe文件的數(shù)量,那又該怎么辦呢?

對(duì)代碼[code19],可以把用連接復(fù)合語句拆分為兩條單獨(dú)的語句,寫成:

@echo off
set num=0
echo %num%
pause  

但是,這不是我們這次想要的結(jié)果。

  對(duì)這兩段代碼都適用的辦法是:使用變量延遲擴(kuò)展語句,讓變量的擴(kuò)展行為延遲一下,從而獲取我們想要的值。

  在這里,我們先來充下電,看看“變量擴(kuò)展”有是怎么一回事。

  用CN-DOS里批處理達(dá)人willsort的原話,那就是:“在許多可見的官方文檔中,均將使用一對(duì)百分號(hào)閉合環(huán)境變量以完成對(duì)其值的替換行為稱之為“擴(kuò)展(expansion)”,這其實(shí)是一個(gè)第一方的概念,是從命令解釋器的角度進(jìn)行稱謂的,而從我們使用者的角度來看,則可以將它看作是引用(Reference)、調(diào)用(Call)或者獲取(Get)?!保ㄒ姡菏裁辞闆r下該使用變量延遲?http://www.cn-dos.net/forum/viewthread.php?tid=20733)說得直白一點(diǎn),所謂的“變量擴(kuò)展”,實(shí)際上就是很簡(jiǎn)單的這么一件事情:用具體的值去替換被引用的變量及緊貼在它左右的那對(duì)百分號(hào)。

  既然只要延遲變量的擴(kuò)展行為,就可以獲得我們想要的結(jié)果,那么,具體的做法又是怎樣的呢?

  一般說來,延遲變量的擴(kuò)展行為,可以有如下選擇:

  1、在適當(dāng)位置使用 setlocal enabledelayedexpansion 語句;
  2、在適當(dāng)?shù)奈恢檬褂?call 語句。

使用 setlocal enabledelayedexpansion 語句,那么,[code19]和[code20]可以分別修改為:

@echo off
setlocal enabledelayedexpansion
set num=0echo !num!
pause復(fù)制內(nèi)容到剪貼板 代碼:@echo off
set num=0
setlocal enabledelayedexpansion
for /f %%i in ('dir /a-d /b *.exe') do (
set /a num+=1
echo num 當(dāng)前的值是 !num!
)
echo 當(dāng)前目錄下共有 %num% 個(gè)exe文件
dir /a-d /b *.txt|findstr "test">nul(
echo 存在含有 test 字符串的文本本件
)||echo 不存在含有 test 字符串的文本文件
if exist test.ini (
echo 存在 test.ini 文件
) else echo 不存在 test.ini 文件
pause  使用第call語句,那么,[code19]和[code20]可以分別修改為: 復(fù)制內(nèi)容到剪貼板 代碼:
@echo off
set num=0call echo %%num%%
pause

代碼:

@echo off
set num=0
for /f %%i in ('dir /a-d /b *.exe') do (
set /a num+=1
call echo num 當(dāng)前的值是 %%num%%
)
echo 當(dāng)前目錄下共有 %num% 個(gè)exe文件
dir /a-d /b *.txt|findstr "test">nul(
echo 存在含有 test 字符串的文本本件
)||echo 不存在含有 test 字符串的文本文件
if exist test.ini (
echo 存在 test.ini 文件
) else 不存在 test.ini 文件
pause

由此可見,如果使用 setlocal enabledelayedexpansion 語句來延遲變量,就要把原本使用百分號(hào)對(duì)閉合的變量引用改為使用感嘆號(hào)對(duì)來閉合;如果使用call語句,就要在原來命令的前部加上 call 命令,并把變量引用的單層百分號(hào)對(duì)改為雙層。 其中,因?yàn)閏all語句使用的是雙層百分號(hào)對(duì),容易使人犯迷糊,所以用得較少,常用的是使用 setlocal enabledelayedexpansion 語句(set是設(shè)置的意思,local是本地的意思,enable是能夠的意思,delayed是延遲的意思,expansion是擴(kuò)展的意思,合起來,就是:讓變量成為局部變量,并延遲它的擴(kuò)展行為)。

  通過上面的分析,我們可以知道:

  1、為什么要使用變量延遲?因?yàn)橐審?fù)合語句內(nèi)部的變量實(shí)時(shí)感知到變量值的變化。
  2、在哪些場(chǎng)合需要使用變量延遲語句?在復(fù)合語句內(nèi)部,如果某個(gè)變量的值發(fā)生了改變,并且改變后的值需要在復(fù)合語句內(nèi)部的其他地方被用到,那么,就需要使用變量延遲語句。而復(fù)合語句有:for語句、if……else語句、用連接符、||和連接的語句、用管道符號(hào)|連接的語句,以及用括號(hào)括起來的、由多條語句組合而成的語句塊。最常見的場(chǎng)合,則是for語句和if……else語句。
  3、怎樣使用變量延遲?
  方法有兩種:
  ① 使用 setlocal enabledelayedexpansion 語句:在獲取變化的變量值語句之前使用setlocal enabledelayedexpansion,并把原本使用百分號(hào)對(duì)閉合的變量引用改為使用感嘆號(hào)對(duì)來閉合;
 ?、?使用 call 語句:在原來命令的前部加上 call 命令,并把變量引用的單層百分號(hào)對(duì)改為雙層。

  “變量延遲”是批處理中一個(gè)十分重要的機(jī)制,它因預(yù)處理機(jī)制而生,用于復(fù)合語句,特別是大量使用于強(qiáng)大的for語句中。只有熟練地使用這一機(jī)制,才能在for的世界中如魚得水,讓自己的批處理水平更上一層樓。很多時(shí)候,對(duì)for的處理機(jī)制,我們一直是霧里看花,即使偶有所得,也只是只可意會(huì)難以言傳。希望大家反復(fù)揣摩,多加練習(xí),很多細(xì)節(jié)上的經(jīng)驗(yàn),是只有通過大量的摸索才能得到的。Good Luck!

變量延遲(setlocal)之淺見

變量延遲,淺見認(rèn)為就是變量預(yù)處理,在事先聲明變量,告訴cmd環(huán)境哪個(gè)先哪個(gè)后。默認(rèn)情況下是停用,可以用兩種方法啟用/停用:

一、cmd /v:on 和cmd /v:off ,范圍在cmd這個(gè)環(huán)境直至exit 出現(xiàn)退出cmd

二、setlocal enabledelayedexpansion和setlocal disabledelayedexpansion范圍在批處理文件范圍內(nèi),直至endlocal出現(xiàn)中止.

先看看官方幫助set /?后以幾個(gè)批處理代碼注釋解釋。

考慮到讀取一行文本時(shí)所遇到的目前擴(kuò)充的限制時(shí),延遲環(huán)境變量擴(kuò)充是很有用的,而不是執(zhí)行的時(shí)候。以下例子說明直接變量擴(kuò)充的問題:

    set VAR=before
    if "%VAR%" == "before" (
        set VAR=after
        if "%VAR%" == "after" @echo If you see this, it worked
    )

不會(huì)顯示消息,因?yàn)樵谧x到第一個(gè) IF 語句時(shí),BOTH IF 語句中的 %VAR% 會(huì)被代替;原因是: 它包含 IF 的文體,IF 是一個(gè)復(fù)合語句。所以,復(fù)合語句中的 IF 實(shí)際上是在比較 "before" 和"after",這兩者永遠(yuǎn)不會(huì)相等。同樣,以下這個(gè)例子也不會(huì)達(dá)到預(yù)期效果:

    set LIST=
    for %i in (*) do set LIST=%LIST% %i
    echo %LIST%

原因是,它不會(huì)在目前的目錄中建立一個(gè)文件列表,而只是將LIST 變量設(shè)成找到的最后一個(gè)文件。這也是因?yàn)?%LIST% 在FOR 語句被讀取時(shí),只被擴(kuò)充了一次;而且,那時(shí)的 LIST 變量是空的。因此,我們真正執(zhí)行的 FOR 循環(huán)是:

    for %i in (*) do set LIST= %i

這個(gè)循環(huán)繼續(xù)將 LIST 設(shè)成找到的最后一個(gè)文件。延遲環(huán)境變量擴(kuò)充允許您使用一個(gè)不同的字符(驚嘆號(hào))在執(zhí)行時(shí)間擴(kuò)充環(huán)境變量。如果延遲的變量擴(kuò)充被啟用,可以將上面例子寫成以下所示,以達(dá)到預(yù)期效果:

    set VAR=before
    if "%VAR%" == "before" (
        set VAR=after
        if "!VAR!" == "after" @echo If you see this, it worked
    )

    set LIST=
    for %i in (*) do set LIST=!LIST! %i
    echo %LIST%

如果命令擴(kuò)展名被啟用,有幾個(gè)動(dòng)態(tài)環(huán)境變量可以被擴(kuò)展,但不會(huì)出現(xiàn)在 SET 顯示的變量列表中。每次變量數(shù)值被擴(kuò)展時(shí),這些變量數(shù)值都會(huì)被動(dòng)態(tài)計(jì)算。如果用戶用這些名稱中任何一個(gè)定義變量,那個(gè)定義會(huì)替代下面描述的動(dòng)態(tài)定義:

%CD% - 擴(kuò)展到當(dāng)前目錄字符串。

%DATE% - 用跟 DATE 命令同樣的格式擴(kuò)展到當(dāng)前日期。

%TIME% - 用跟 TIME 命令同樣的格式擴(kuò)展到當(dāng)前時(shí)間。

%RANDOM% - 擴(kuò)展到 0 和 32767 之間的任意十進(jìn)制數(shù)字。

%ERRORLEVEL% - 擴(kuò)展到當(dāng)前 ERRORLEVEL 數(shù)值。

%CMDEXTVERSION% - 擴(kuò)展到當(dāng)前命令處理器擴(kuò)展名版本號(hào)。

%CMDCMDLINE% - 擴(kuò)展到調(diào)用命令處理器的原始命令行。

開始批處理文件中環(huán)境改動(dòng)的本地化操作。在執(zhí)行 SETLOCAL 之后所做的環(huán)境改動(dòng)只限于批處理文件。要還原原先的設(shè)置,必須執(zhí)行 ENDLOCAL。達(dá)到批處理文件結(jié)尾時(shí),對(duì)于該批處理文件的每個(gè)尚未執(zhí)行的 SETLOCAL 命令,都會(huì)有一個(gè)隱含的 ENDLOCAL 被執(zhí)行。

SETLOCAL

如果命令擴(kuò)展名被啟用,SETLOCAL 會(huì)如下改變:

SETLOCAL 批命令現(xiàn)在可以接受可選參數(shù):
ENABLEEXTENSIONS / DISABLEEXTENSIONS
啟動(dòng)或停用命令處理器擴(kuò)展名。詳細(xì)信息,請(qǐng)參閱 CMD /?。
ENABLEDELAYEDEXPANSION / DISABLEDELAYEDEXPANSION
啟動(dòng)或停用延緩環(huán)境變量擴(kuò)展名。詳細(xì)信息,請(qǐng)
參閱 SET /? 。
無論在 SETLOCAL 命令之前它們的設(shè)置是什么,這些修改會(huì)一直保留到匹配的 ENDLOCAL 命令。如果有一個(gè)參數(shù),SETLOCAL 命令將設(shè)置 ERRORLEVEL 的值。如果有兩個(gè)有效參數(shù)中的一個(gè),該值則為零。用下列技巧,您可以在批腳本中使用這個(gè)來決定擴(kuò)展名是否可用:

VERIFY OTHER 2>nul
SETLOCAL ENABLEEXTENSIONS
IF ERRORLEVEL 1 echo Unable to enable extensions

這個(gè)方法之所以有效,是因?yàn)樵?CMD.EXE 的舊版本上,SETLOCAL不設(shè)置 ERRORLEVEL 值。具有不正確參數(shù)的 VERIFY 命令將ERRORLEVEL 值初始化成非零值。

官方解釋有些讓人犯迷糊,以下幾個(gè)代碼注釋部分來解釋變量延遲,紕漏之處,請(qǐng)高手斧正.

@echo offsetlocal enabledelayedexpansion
::第一方演示變量延遲,當(dāng)輸出if you ..延遲啟動(dòng)
::var重復(fù)賦值,第一個(gè)%var%取的是before
::第二個(gè)!var!取的是after,若不開啟延遲變量
::不顯示因!VAR!取的是before
set VAR=before
if "%VAR%" == "before" (
set VAR=after
if "!VAR!" == "after" @echo If you see this, it worked
)
pause>nul
@echo offsetlocal enabledelayedexpansion
:: 演示變量延遲,用setlocal disabledelayedexpansion
:: 和setlocal enabledelayedexpansion 相互切換
:: echo %var% 取set var=fds 的值,而echo !var!
:: 取for復(fù)合語句中set var=%%i的值;%var%的值與變量延遲
:: setlocal開關(guān)無關(guān),但!var!的值與之相關(guān)。當(dāng)變量延遲
:: 處于開狀態(tài)則取%%i的賦值,反之則取!var!本身.
set var=fds
for /l %%i in (1,1,6) do (
set var=%%i
echo %var%
echo !var!
)
pause>nulexit
@echo offsetlocal enabledelayedexpansion
::變量里套變量延遲演示
set a=40000
set b=df
set a%b%=70000
set c=!a%b%!
echo %c%
pause>nul
@echo offsetlocal enabledelayedexpansion
::顯示2個(gè)隨機(jī)數(shù)并截取各數(shù)字求和
mode con:cols=40 lines=20 1>nul
color a1
set %random%=%random%
for /f "delims=" %%i in ('set') do set num=%%icall echo %%num%%goto be
:be
for /f "tokens=1,2 delims==" %%j in ("%num%") do (
set/a a=%%j
set/a b=%%k
)
for /f %%l in ("%a%%b%") do (
set/a a=%%l
set/a b=%%l
set/a a0=%a:~0,1%
set/a a1=%a:~1,1% 2>nulset/a a1+=!a0!
set/a a2=%a:~2,1% 2>nulset/a a2+=!a1!
set/a a3=%a:~3,1% 2>nulset/a a3+=!a2!
set/a a4=%a:~4,1% 2>nulset/a a4+=!a3!
set/a b0=%b:~0,1%
set/a b1=%b:~1,1% 2>nulset/a b1+=!b0!
set/a b2=%b:~2,1% 2>nulset/a b2+=!b1!
set/a b3=%b:~3,1% 2>nulset/a b3+=!b2!
set/a b4=%b:~4,1% 2>nulset/a b4+=!b3!
)
set/a b4+=%a4%
echo 和為:%b4%
pause>nul

以下內(nèi)容為mq0036個(gè)人補(bǔ)充:
先來看個(gè)變量延遲的例子:

@echo off

setlocal
set aa=aaa:bbb
call :ck %aa%
echo return=%str%
call :ddd
goto :eof
 
:ck
setlocal EnableDelayedExpansion
if "a"=="a" (set str2=ErrorOperation) else (
echo else
for /f "tokens=1,* delims=:" %%m in ("%~1") do (
set str1=%%~m
if /I "!str1!"=="aaa" set str2=%%~n
)
)
endlocal  set str=%str2%
goto :eof
 
:ddd
echo %zzz%
set zzz=old
goto :eof

相信各位對(duì)上面的程序都能看懂,不過我這里還要寫點(diǎn)廢話解釋解釋,高手請(qǐng)?zhí)^。

1.使用setlocal設(shè)置變量為局部變量,結(jié)束標(biāo)志是endlocal,如果不是有endlocal則作用范圍表示到當(dāng)前文件結(jié)束.
2.變量延遲使用setlocal EnableDelayedExpansion和setlocal DisableDelayedExpansion,如果不使用setlocal DisableDelayedExpansion則作用范圍表示到當(dāng)前文件結(jié)束.
      說明:DisableDelayedExpansion只是關(guān)閉變量延遲,也就是在這個(gè)語句后面的無法使用變量延遲的功能(后面還有講解)
3.if語句后如果要執(zhí)行多條語句需要把多條語句使用括號(hào)括起來,當(dāng)使用else時(shí),即使if后只有單條語句,也要括起來。
BAT語法認(rèn)為括號(hào)中的語句就是一條語句。

程序說明:
說變量延遲就要說到局部變量,如果他們嵌套使用,各個(gè)變量的取值會(huì)怎么樣?
第三行,設(shè)置局部變量
:ck子程序的功能,是利用延遲把a(bǔ)a變量中根據(jù)冒號(hào)(:)分割提取字符串,并且?guī)Щ胤指詈蟮淖址?br /> :ddd子程序則是為了驗(yàn)證程序前面的setlocal的嵌套的作用域
程序運(yùn)行方式:把程序保存為bat文件,運(yùn)行cmd并切換到程序所在目錄,運(yùn)行程序,如果修改了程序則關(guān)閉當(dāng)前cmd窗口重新打開cmd。

驗(yàn)證一:

把第三行的setlocal去掉,然后多次運(yùn)行程序,可以看出第一次執(zhí)行時(shí),echo %zzz%輸出的是ECHO is off.后面再次執(zhí)行的都輸出了old字符串。
程序運(yùn)行方式:把程序保存為bat文件,運(yùn)行cmd并切換到程序所在目錄,輸入程序文件名運(yùn)行
程序運(yùn)行方式:把程序保存為bat文件,運(yùn)行cmd并切換到程序所在目錄,運(yùn)行程序,如果修改了程序則關(guān)閉當(dāng)前cmd窗口重新打開cmd。

驗(yàn)證二:

使用endlocal set str=%str2%是為了把局部變量返回主調(diào)函數(shù)中
多次調(diào)用執(zhí)行該文件,變量echo %zzz%中的值都是空
程序運(yùn)行方式:把程序保存為bat文件,運(yùn)行cmd并切換到程序所在目錄,運(yùn)行程序,如果修改了程序則關(guān)閉當(dāng)前cmd窗口重新打開cmd。

驗(yàn)證三:
在BAT文件中的一部分是局部變量,一部分是全局變量。修改程序代碼如下:

setlocal
echo %aa%
set aa=aaa:bbb
::endlocal
call :ddd
endlocal
goto :eof
:ddd
echo %zzz%
set zzz=old
goto :eof

通過改變endlocal的位置可以看到,在調(diào)用語句的后面,但在子程序的前面使用,則會(huì)起到局部變量的效果,當(dāng)放到調(diào)用語句的前面則是全局變量的效果。這里測(cè)試的是在主程序中調(diào)用setlocal的功能,所以endlocal也必須在主程序中使用。
而且setlocal跟子程序有關(guān),如果在子程序中使用setlocal,則在該子程序結(jié)束前的endlocal有效,如果不寫endlocal則默認(rèn)作用域到子程序結(jié)束,也就是在子程序中使用setlocal則作用域不會(huì)超出子程序??聪旅娴氖纠?/p>

@echo off
echo %aa%
set aa=aaa:bbb
call :bbb
call :ddd
goto :eof

:bbb
setlocal
echo %zzz%
set zzz=old
::endlocal
echo %xxx%
set xxx=xxx
goto :eof

:ddd
echo %y%
set y=yyyy

運(yùn)行以上程序,把:bbb子程序中的endlocal啟用和禁用,可以查看變量%zzz%和%xxx%的值,
程序運(yùn)行方式:把程序保存為bat文件,運(yùn)行cmd并切換到程序所在目錄,運(yùn)行程序,如果修改了程序則關(guān)閉當(dāng)前cmd窗口重新打開cmd。

驗(yàn)證四:
把if "a"=="a" (set str2=ErrorOperation)...... 這個(gè)語句中的括號(hào)拿掉,不管條件是否成立,"a"=="a"或"a"=="b",則都會(huì)執(zhí)行else里的語句
程序運(yùn)行方式:把程序保存為bat文件,運(yùn)行cmd并切換到程序所在目錄,運(yùn)行程序,如果修改了程序則關(guān)閉當(dāng)前cmd窗口重新打開cmd。

驗(yàn)證五:

延遲的啟用與禁用,修改ck子程序,如下:

:ck
setlocal EnableDelayedExpansion
if "a"=="b" (set str2=ErrorOperation)  else (
echo else
for /f "tokens=1,* delims=:" %%m in ("%~1") do (
set str1=%%~m
if /I "!str1!"=="aaa" set str2=%%~n
)
)
::setlocal DisableDelayedExpansion
for /l %%i in (1,1,3) do (set num=%%i
echo !num!)
setlocal DisableDelayedExpansion
goto :eof

把setlocal DisableDelayedExpansion放到for語句之前和之后的區(qū)別,你自己可以測(cè)試看看效果,從這里個(gè)程序可以看到啟用和禁用的區(qū)別。
程序運(yùn)行方式:把程序保存為bat文件,運(yùn)行cmd并切換到程序所在目錄,運(yùn)行程序,如果修改了程序則關(guān)閉當(dāng)前cmd窗口重新打開cmd。

以上就是變量延遲詳解 call setlocal的詳細(xì)內(nèi)容,更多關(guān)于call setlocal的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

標(biāo)簽:韶關(guān) 通遼 海北 阿里 昌都 滄州 咸寧 資陽(yáng)

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《變量延遲詳解 call setlocal》,本文關(guān)鍵詞  變量,延遲,詳解,call,setlocal,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《變量延遲詳解 call setlocal》相關(guān)的同類信息!
  • 本頁(yè)收集關(guān)于變量延遲詳解 call setlocal的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章