2013-02-08 27 views
2

此問題最初來自Escape percent signs in given variables。我不想在那邊解散好的答案。但我的問題改變了一點點...當通過CALL時百分號消失

讓我們假設有一個給定的字符串變量用雙引號引起來,它可能包含一個或多個百分比符號。無法切換到啓用延遲擴展(其他代碼已可用)。調用包含字符串變量作爲參數的函數是必要的。這是我到目前爲止確定的:

@echo off & setlocal ENABLEEXTENSIONS 
SET AlbumArtist=%1 
CALL :EscapePoisonChars %AlbumArtist% AlbumArtist_VDN 
echo %AlbumArtist_VDN% 

CALL :EscapePoisonChars %%AlbumArtist%% AlbumArtist_VDN 
echo %AlbumArtist_VDN% 
endlocal &GOTO:EOF 

:EscapePoisonChars 
@echo off & setlocal ENABLEEXTENSIONS 
SET TmpString="%~1" 
SET TmpString=%TmpString:&=^^^&% 
SET TmpString=%TmpString:(=^^^(% 
SET TmpString=%TmpString:)=^^^)% 
endlocal&SET %2=%TmpString:~1,-1%&GOTO :EOF 

我知道這可能不是一個「乾淨的解決方案」。但我想知道爲什麼當例程被CALL :EscapePoisonChars %AlbumArtist% AlbumArtist_VDN調用時百分號消失。當與字符串變量%%AlbumArtist%%稱爲封閉的一倍百分號它提供了所需的輸出:

D:\Batch>PercentTwins.bat "100% Rock & Roll" 
100 Rock & Roll 
100% Rock & Roll 

D:\Batch> 

爲何會有不同的結果,如果%AlbumArtist%擴大輸入或功能:EscapePoisonChars外面?隨着回聲我看到百分號只是消失SET TmpString="~1"。任何解釋都會幫助我改進我的更進一步的CMD技術。謝謝!

回答

1

如果我錯了,任何人都會糾正我,但我認爲當一個命令中的單個百分號傳遞給另一個命令時,它們將消失。如果它只是在同一個命令中使用,它通常不會消失。

(有可能是這樣說的更「正確」的方式,還是這種想法可能是錯誤的共)

(上在Microsoft Support website百分號一些信息)

+0

5分鐘達到上限:-)現在我看到你所提到的微軟知識庫和它說,一個百分號將被解釋爲一個NUL CHARAC當由回聲處理時。通過嘗試,我發現當字符串用雙引號括起來時,單個百分號也會被回顯。現在我通過CALL解析雙引號字符串,並且行爲完全改變。奇怪。馬丁 – CmdQuestion 2013-02-08 17:12:09

0

call命令啓動%解析第二階段(參考How does the Windows Command Interpreter (CMD.EXE) parse scripts?的問題接受答案);這讓%標誌消失。你可能會增加一倍提前%跡象,但你會需要啓用delayed expansion的是,像這樣的:

@echo off & setlocal ENABLEEXTENSIONS EnableDelayedExpansion 
SET AlbumArtist=%1 
set AlbumArtist=!AlbumArtist:%%=%%%%! 
CALL :EscapePoisonChars %AlbumArtist% AlbumArtist_VDN 
echo %AlbumArtist_VDN% 
endlocal &GOTO:EOF 

在你的第二個子程序調用,這兩個分析階段沒有看到過的的%跡象原始字符串;從字面上看,第一階段將%%AlbumArtist%%擴展爲%AlbumArtist%,第二階段將其擴展爲100% Rock & Roll

但是:
沒有必要對所有這一切,你不需要在子程序的一切,當你堅持的唯一安全set語法和保證總是有字符串引用正確:

set "AlbumArtist=%~1" 

%1會返回給定的字符串; %~1刪除潛在的引號。將整個賦值表達式用引號括起來,使得對於而不是的有害字符的語法穩健,將""作爲分配的字符串本身的一部分。

當使用/返回字符串(由echo在這裏的例子),你需要附上報價再次保持安全中的字符串,如果你使用的是正常的(即時)%擴展:

set "AlbumArtist=%~1" 
echo "%AlbumArtist%" 

另外,延遲擴展使閱讀變量安全的,即使不帶引號:

set "AlbumArtist=%~1" 
setlocal EnableDelayedExpansion 
echo !AlbumArtist! 
endlocal