一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

腳本之家,腳本語言編程技術(shù)及教程分享平臺!
分類導(dǎo)航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務(wù)器之家 - 腳本之家 - bat - 變量延遲詳解 call setlocal

變量延遲詳解 call setlocal

2021-10-08 00:56腳本之家 bat

變量延遲在for語句中起著至關(guān)重要的作用,不只是在for語句中,在其他的復(fù)合語句中,它也在幕后默默地工作著,為了突出它的重要性,本節(jié)內(nèi)容在單獨(dú)的樓層中發(fā)出來,希望引起大家的重視

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

  例如,你編寫了這樣一個代碼:

?
1
2
3
@echo off
set num=0&&echo %num%
pause

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

  之所以會出錯,是因為“變量延遲”這個家伙在作怪。

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

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

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

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

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

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

  正是如此。

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

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@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% 個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í)行特點(diǎn)是“逐條”執(zhí)行而不是“逐行”執(zhí)行,澄清了這個誤解,將會更加理解批處理的預(yù)處理機(jī)制。

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

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

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

  結(jié)合上面兩個例子,我們再來分析一下,為什么這兩段代碼的執(zhí)行結(jié)果和我們的期望有一些差距。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@echo off
setlocal enabledelayedexpansion
set num=0&&echo !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% 個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=0&&call echo %%num%%
pause

代碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@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% 個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 語句來延遲變量,就要把原本使用百分號對閉合的變量引用改為使用感嘆號對來閉合;如果使用call語句,就要在原來命令的前部加上 call 命令,并把變量引用的單層百分號對改為雙層。 其中,因為call語句使用的是雙層百分號對,容易使人犯迷糊,所以用得較少,常用的是使用 setlocal enabledelayedexpansion 語句(set是設(shè)置的意思,local是本地的意思,enable是能夠的意思,delayed是延遲的意思,expansion是擴(kuò)展的意思,合起來,就是:讓變量成為局部變量,并延遲它的擴(kuò)展行為)。

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

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

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

變量延遲(setlocal)之淺見

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

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

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

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

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

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

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

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

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

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

這個循環(huán)繼續(xù)將 LIST 設(shè)成找到的最后一個文件。延遲環(huán)境變量擴(kuò)充允許您使用一個不同的字符(驚嘆號)在執(zhí)行時間擴(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ò)展名被啟用,有幾個動態(tài)環(huán)境變量可以被擴(kuò)展,但不會出現(xiàn)在 SET 顯示的變量列表中。每次變量數(shù)值被擴(kuò)展時,這些變量數(shù)值都會被動態(tài)計算。如果用戶用這些名稱中任何一個定義變量,那個定義會替代下面描述的動態(tài)定義:

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

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

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

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

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

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

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

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

SETLOCAL

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

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

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

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

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

?
1
2
3
4
5
6
7
8
9
10
11
@echo off&setlocal enabledelayedexpansion
::第一方演示變量延遲,當(dāng)輸出if you ..延遲啟動
::var重復(fù)賦值,第一個%var%取的是before
::第二個!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
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@echo off&setlocal 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>nul&exit
?
1
2
3
4
5
6
7
8
@echo off&setlocal enabledelayedexpansion
::變量里套變量延遲演示
set a=40000
set b=df
set a%b%=70000
set c=!a%b%!
echo %c%
pause>nul
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
@echo off&setlocal enabledelayedexpansion
::顯示2個隨機(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=%%i&call 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>nul&set/a a1+=!a0!
set/a a2=%a:~2,1% 2>nul&set/a a2+=!a1!
set/a a3=%a:~3,1% 2>nul&set/a a3+=!a2!
set/a a4=%a:~4,1% 2>nul&set/a a4+=!a3!
set/a b0=%b:~0,1%
set/a b1=%b:~1,1% 2>nul&set/a b1+=!b0!
set/a b2=%b:~2,1% 2>nul&set/a b2+=!b1!
set/a b3=%b:~3,1% 2>nul&set/a b3+=!b2!
set/a b4=%b:~4,1% 2>nul&set/a b4+=!b3!
)
set/a b4+=%a4%
echo 和為:%b4%
pause>nul

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@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

相信各位對上面的程序都能看懂,不過我這里還要寫點(diǎn)廢話解釋解釋,高手請?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)閉變量延遲,也就是在這個語句后面的無法使用變量延遲的功能(后面還有講解)
3.if語句后如果要執(zhí)行多條語句需要把多條語句使用括號括起來,當(dāng)使用else時,即使if后只有單條語句,也要括起來。
BAT語法認(rèn)為括號中的語句就是一條語句。

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

驗證一:

把第三行的setlocal去掉,然后多次運(yùn)行程序,可以看出第一次執(zhí)行時,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。

驗證二:

使用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。

驗證三:
在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)用語句的后面,但在子程序的前面使用,則會起到局部變量的效果,當(dāng)放到調(diào)用語句的前面則是全局變量的效果。這里測試的是在主程序中調(diào)用setlocal的功能,所以endlocal也必須在主程序中使用。
而且setlocal跟子程序有關(guān),如果在子程序中使用setlocal,則在該子程序結(jié)束前的endlocal有效,如果不寫endlocal則默認(rèn)作用域到子程序結(jié)束,也就是在子程序中使用setlocal則作用域不會超出子程序。看下面的示例:

@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。

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

驗證五:

延遲的啟用與禁用,修改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ū)別,你自己可以測試看看效果,從這里個程序可以看到啟用和禁用的區(qū)別。
程序運(yùn)行方式:把程序保存為bat文件,運(yùn)行cmd并切換到程序所在目錄,運(yùn)行程序,如果修改了程序則關(guān)閉當(dāng)前cmd窗口重新打開cmd。

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

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 糖心vlog网页版 | 久久电影精品久久99久久 | 99在线观看视频免费 | 国产自拍视频一区 | 精品久久久久香蕉网 | 男女姓交大视频免费观看 | 骚虎最新网址 | 天天色资料 | 插入逼 | 国产精品永久免费自在线观看 | sedog在线长片| 日韩高清一区二区三区不卡 | 不良小说 | 国产91短视频 | 红色毛片| 成年性香蕉漫画在线观看 | 国产精品成人网红女主播 | 小柔的性放荡羞辱日记动漫 | 青青草国产青春综合久久 | 国产视频一区在线观看 | 久久青青草原综合伊人 | 亚洲va久久久噜噜噜久久狠狠 | 奇米影视999| 国产成人免费观看在线视频 | 美女69xx | 1769最新资源站 | 国产99页| 亚洲国产精品久久久久久网站 | 国产欧美日韩不卡一区二区三区 | 欧美香蕉 | 亚洲欧洲淘宝天堂日本 | 果冻传媒mv在线观看入口免费 | 色就色综合 | 国产主播福利在线观看 | 图片专区小说专区卡通动漫 | 国产区久久 | 欧美一级特黄特色大片免费 | 男人机机桶女人 | 亚洲欧美天堂综合久久 | 久久成人永久免费播放 | 久久夜色噜噜噜亚洲AV0000 |