批處理文章 預處理 變數延遲 call

2021-05-28 02:53:21 字數 4138 閱讀 1352

三、call引出的一些問題

(一)call與脫字字元

例、@echo off

set /p var=、|等。這裡請允許我自定義兩個名詞:

主預處理過程:系統本身預處理過程的總稱,其中包括了%%型和!!型。

次預處理過程:由於call命令引起的預處理過程的總稱。

「其它特殊字元」是在主預處理過程中被系統識別的,而在次預處理

過程中對這些符號的識別是有問題的。

例、@echo off

call echo hero!^&pause

pause

本例中,經過主預處理過程,&被識別為普通字元,而在次預處理過程中符號&的識別將產生問題。正如《命令列參考》中提到的--不要在 call 命令中使用管道和重定向符號。(這倒不是說call語句中不能使用那些符號,而是這些符號不能作為引數傳遞給call命令。)

這也從某種程度上說明某行語句的句子結構(一條還是多條)和功能(是從定向輸出還是其它)是在主預處理過程中確定的。

以上所有內容,只是我個人的看法,由於沒有官方文件的支援,因

此僅供參考。

那麼我們學了以上種種內容又有什麼實際用途呢?我想,懂得了以上

道理就可以寫出更加個性化的**,同時也可以作為一種偽裝術在實

際中應用。

@echo off

set ^&=setlocal enabledelayedexpansion

set ^^^^^hero=^^^^^&p

set ^au=^^^au

set ^^^^^^^^^=障眼法

%&%set ^^^^^se=^^^se!

echo %^^^^%!%^^hero%!au%^se%

怎麼樣,這段**能看明白嗎?

正好對call的這種用法不了解呢,學習了

不過正好今天早上查到了關於一篇關於call不錯的文章(個人想法),在此與大家分享

**大家都知道call命令是用來呼叫其他程式的。

想必有一定經驗的朋友都知道要輸出%a%需要這樣寫「echo %%a%%」,這樣

百分號會脫掉乙個。

先以乙個簡單的echo作為引子:

例一、@echo off

set a=b

echo %a%

echo %%a%%

echo %%%a%%%

echo %%%%a%%%%

echo %%%%%a%%%%%

pause

執行結果是:

b%a%

%b%%%a%%

%%b%%

解說:不知道大家看沒看出來問題。批處理中類似於這樣的變數替換究竟是

如何進行的呢?我們姑且稱之為「替換步驟」

「替換步驟」大體分為兩步:

第一步:

當百分號「%」是偶數時(只按一邊的百分號數目計算),變數將

不被替換,其它的也不變。當百分號是奇數時(也只按一邊的百分號數目計

),最裡層的「%a%」將被替換成變數的值,此時百分號數目將少了乙個(

只按一邊計)。

第二步:

第一步完成後,百分號就都是偶數了。好了,現在把百分號數目的

一半脫掉,剩下的就是結果了。

拿本例的「echo %%%%%a%%%%%」為例說明一下。第一步,由於百分號有

5個是奇數,因此最裡層的%a%被其值代替,現在變為「%%%%b%%%%」;第二

步,將百分號脫去一半,就變為「%%b%%」。怎麼樣,理解了嗎?

再看看有call的時候。

例二、@echo off

set a=b

set b=c

set c=d

call echo %%%%%%%%a%%%%%%%%

call echo %%%%%%%%%%%%%a%%%%%%%%%%%%%

pause

執行結果是:

%%a%%

%%%b%%%

解說:由於有call的存在,「替換步驟」就會多進行一次。以「call echo

%%%%%%%%%%%%%a%%%%%%%%%%%%%」為例。

「替換步驟」第一次:

第一步:

百分號有13個是奇數,因此最裡層的「%a%」被其值b替換,此時為

「%%%%%%%%%%%%b%%%%%%%%%%%%」,現在百分號數目為12個了。

第二步:

將百分號數脫去一半,現在為「%%%%%%b%%%%%%」。

「替換步驟」第二次:

第一步:

百分號有6個是偶數,因此不替換。現在仍然是「%%%%%%b%%%%%%」。

第二步:

將百分號數脫去一半,現在為「%%%b%%%」。

結果就是「%%%b%%%」。

(如果有n個call那麼就要進行n+1次「替換步驟」。)

call命令在「變數延遲」中也遵循「替換步驟」。

舉個例子:我現在要將字串str1的「superhero」部分替換為chess,在此我們用間接的方法實現。**如下:

@echo off

set str1=mynameissuperhero

set str2=supxrhxro

set a=x

call call set str3=%%%%str1:%%str2:%a%=e%%=chess%%%%

echo %str3%

pause

因為用了兩個call,因此要進行3次「替換步驟」。

「替換步驟」第一次:

1、將「%a%」替換成「x」,結果為「%%%%str1:%%str2:x=e%%=chess%%%%」。

2、將百分號脫去一半,為「%%str1:%str2:x=e%=chess%%」。

「替換步驟」第二次:

1、將「%str2:x=e%」替換掉,結果為「%%str1:superhero=chess%%」。

2、將百分號脫去一半,為「%str1:superhero=chess%」。

「替換步驟」第三次:

1、將「%str1:superhero=chess%」替換掉,結果為「mynameischess」。

2、將百分號脫去一半(沒的脫了),因此結果為「mynameischess」。

@echo off

setlocal enabledelayedexpansion

set var=hero

echo !var!^^^^^>

pause

執行的結果為:「hero^>」。我們來分析一下,進行第一次預處理時,由於「!var!」,因此先不替換變數值而進行特殊符號的處理,處理完後就成了「echo !var!^^>」;之後再進行一次預處理,此時就要替換「!var!」了,處理完後就成了「echo hero^>」。

複製**

這個解釋跟前面的觀點矛盾了吧:

根據我的經驗,預處理要做的是變數值的替換和特殊符號的處理。究竟先執行哪個操作呢,我認為要先進行變數值的替換。

複製**

是不是說的有點亂哦?

按照作者前面的觀點,我也可以理解成:第一次預處理時結果是:echo hero^^>,第二次與處理時結果是:echo hero^>,最後的結果就是:echo hero^>,不是照樣說得通嗎?

如果作者的前面觀點是正確的話,我想可以這樣總結(個人):

預處理:每條語句執行前都會進行從變數替換(如果有的話)到轉義特殊符號(如果有的話)的動作過程。

有下面2種情況:

(1)沒有開啟setlocal enabledelayedexpansion:只進行一次預處理,且用雙引號包裹的內容原封不動。

(2)有開啟setlocal enabledelayedexpansion:①語句中含有!:進行兩次預處理,且不管是否用雙引號包裹。②語句中不含!:與情況(1)相同。

關於「預處理」不能簡單的歸結為一次兩次,其實有很多次的,每一次處理的內容都不完全相同,甚至完全不同。

預處理過程包含對特殊字元的解釋、引數的識別等,其中特殊字元的解釋又包含了變數的替換(微軟體擴充套件)。

第一階段預處理發生在cmd.exe讀取時,是無條件進行的,此時命令還沒有被識別出來。

第二階段處理發生在命令被執行時,是由具體的命令進行,這個階段的處理有很強的針對性。

這兩個階段的預處理內容可是比較複雜的,每乙個階段又可以劃分為很多層次。

還有第一階段處理的某些內容第二階段會重複處理,或者第一階段沒有處理的第二階段會接著處理。

好吧,也許我所說的只有我自己能理解。

其實我也是個新人。

批處理中處理變數延遲

rem 比較兩種異同 體會變數延遲 echo off set a 4 set a 5 echo a pause setlocal enabledelayedexpansion set c 4 set c 5 echo c pause批處理執行機制 批處理讀取命令按行讀取,在處理之前要完成必要的預處理...

批處理的延遲變數擴充套件

set num 0 for l i in 1,1,10 do set a num 1 echo i,num 這個程式應該輸出 1,12,2 3,34,4 5,56,6 7,78,8 9,910,10 實際輸出 1,02,0 3,04,0 5,06,0 7,08,0 9,010,0 這是因為批處理程式...

批處理 延遲環境變數擴充套件

延遲變數全稱 延遲環境變數擴充套件 要理解這個東西 我們還得先理解一下什麼叫擴充套件 cmd 在解釋我們的命令的時候 首先會讀取命令列一條完整的命令 然後對其進行一些命令格式的匹配操作 看你所輸入的命令格式是不是符合他的要求.如果我們要在我們的命令中引用一些變數,那麼我們如何讓 cmd在解釋我們的命...