三、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在解釋我們的命...