2013-03-10 200 views
3

我真的好奇爲什麼我的字符串替換過程在解析包含任何特殊字符(包括感嘆號)的文本文件時起作用。我預計延遲變量擴展將關閉符號,百分號等特殊的含義,但反而會失敗感嘆號...Cmd和感嘆號 - 第二部分

代碼:

@echo on & setlocal ENABLEEXTENSIONS 

set "InFile=%~1" 
set "OutFile=%~2" 
set "Replace=%~3" 

CALL :ParseCue "%%InFile%%" "%%OutFile%%" "%%Replace%%" 

endlocal &GOTO:EOF 

:ParseCue 
@echo on & setlocal ENABLEEXTENSIONS DISABLEDELAYEDEXPANSION 
set "FileToParse=%~1" 
set "OutputFile=%~2" 
set "NewExtension=%~3" 
for /F "usebackq tokens=* delims=" %%a in ("%FileToParse%") DO (
    set "line=%%a" 
    @echo on & setlocal ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION 
    set "line=!line:.wav=%NewExtension%!" 
    echo(!line!>>"%OutputFile%" 
    endlocal 
) 
endlocal &GOTO:EOF 

InputFile.txt:

This a test for parsing lines with special characters 
Rock & Roll.wav 
Rock & Roll!.wav 
Special | < > ~ \ ²³ { [ ] } ! " ´ ' ` üäö @ ; : € $ % &/() = ? chars.wav 

命令行語法:

D:\Users\Public\Batch\YAET>parse.bat "InputFile.txt" "OutputFile.txt" ".flac" 

OutputFile.txt:

This a test for parsing lines with special characters 
Rock & Roll.flac 
Rock & Roll!.flac 
Special | < > ~ \ ²³ { [ ] } ! " ´ ' ` üäö @ ; : € $ % &/() = ? chars.flac 

編輯/補充:

後1年半,我不得不再次使用這個代碼片斷。請參閱另外兩個處理有毒字符的示例。第一個使用臨時啓用延遲擴展(請參閱Ansgars答案),第二個使用CALL。兩者都將解析當前目錄中和下方的非空文件的路徑和名稱,但不會將驅動器盤符和路徑拖尾到當前目錄。

實施例#1(在set "File=!File..."圍雙引號和不需要echo "!FILE!">>...):

@echo off & setlocal ENABLEEXTENSIONS DISABLEDELAYEDEXPANSION 
del NonEmptyFiles.txt >NUL 2>&1 
echo Searching non-empty files in and below current directory ... 
for /f "tokens=*" %%I in ('dir /s /b /a:-D') do (
    if not %%~zI==0 (
     set "File=%%I" 
     setlocal ENABLEDELAYEDEXPANSION 
     set "File=!File:%cd%\=!" 
     echo "!File!">> NonEmptyFiles.txt 
     endlocal 
     ) 
    ) 
echo Done. See NonEmptyFiles.txt. 
endlocal &goto:EOF 

實施例#2(較慢,封裝需要雙引號):用於

@echo off & setlocal ENABLEEXTENSIONS DISABLEDELAYEDEXPANSION 
del NonEmptyFiles.txt >NUL 2>&1 
echo Searching non-empty files in and below current directory ... 
for /f "tokens=*" %%i in ('dir /s /b /a:-D') do (
    if not %%~zi==0 (
     set "File=%%i" 
     call set "File=%%File:%cd%\=%%" 
     call echo "%%File%%">> NonEmptyFiles.txt 
     ) 
    ) 
echo Done. See NonEmptyFiles.txt. 
endlocal &goto:EOF 

文件和文件夾測試:

D:\Martin\Any & Path>dir /s /b /a:-D 
D:\Martin\Any & Path\Hello! World!.txt 
D:\Martin\Any & Path\Rock & Roll\!File! !!File!!.txt 
D:\Martin\Any & Path\Rock & Roll\%File% %%File%% %%I.txt 
D:\Martin\Any & Path\Rock & Roll\Poison! !§$%&()=`´'_;,.-#+´^ßöäüÖÄÜ°^^#.txt 
D:\Martin\Any & Path\Rock & Roll\SizeZero.txt 

產量:

D:\Martin\Any & Path>stringinforloop.bat 
Searching non-empty files in and below current directory ... 
See NonEmptyFiles.txt. Done. 

D:\Martin\Any & Path>type NonEmptyFiles.txt 
"Hello! World!.txt" 
"Rock & Roll\!File! !!File!!.txt" 
"Rock & Roll\%File% %%File%% %%I.txt" 
"Rock & Roll\Poison! !§$%&()=`´'_;,.-#+´^ßöäüÖÄÜ°^^#.txt" 

享受配料!馬丁

回答

6

那是因爲你啓用延遲擴展set "line=%%a"

set "line=%%a" 
@echo on & setlocal ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION 
set "line=!line:.wav=%NewExtension%!" 

如果你啓用延遲擴展分配%%a前:

@echo on & setlocal ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION 
set "line=%%a" 
set "line=!line:.wav=%NewExtension%!" 

你會得到

Special | <>〜\³³{[]}€$%& /()=? chars.flac

,而不是

專題| <>〜\³³{[]}! 「''üäö@;:€$%& /()=?chars。FLAC


編輯:延遲擴展控件時,在一份聲明變量擴展。在腳本中的關鍵語句是線

set "line=%%a" 

其分配循環變量%%a給變量line值。在禁用延遲擴展的情況下,分配%%a的文字值,因爲腳本解釋器在解析時無法擴展%%a。但是,如果啓用延遲擴展,則bang變量會在執行時展開,因此解釋器將查看%%a的值並在將結果分配給變量line之前將其中的任何!whatever!展開。

也許它會變得更清晰的例子。如果你添加一條線

%foo%!foo!

到輸入文件並定義在腳本變量:

@echo on & setlocal ENABLEEXTENSIONS 

set "foo=bar" 
set "InFile=%~1" 
... 

當啓用後set "line=%%a"既不%foo%也不!foo!延遲擴展%%a之前被擴展被分配給變量line(該解釋器在執行時間之前看不到%%a的值),所以你得到這個輸出:

%foo%!foo!

當您啓用set "line=%%a"解釋將擴大砰變量結果賦給變量line之前,所以你得到這個輸出之前延遲擴展

%FOO%吧

%foo%只會在解析時展開,此時解釋器無法看到%%a的實際值,因此%foo%在這裏仍然是一個文字%foo%

set "line=!line:.wav=%NewExtension%!"此外分配不影響劉海或百分號可變內,因爲擴展無法傳遞,即,它轉換到!line!%foo% bar(或%foo% !foo!),然後停止。

不過,您可以使用call命令強制擴展變量(%)。一個命令call set "line=!line!"第一膨脹以call set "line=%foo% bar"在當前上下文中,然後在call新的上下文,其中%foo%膨脹以bar,以及評估set "line=%foo% bar",所以可變line被分配值bar bar


正如旁註:你的代碼太複雜了。你會得到與此完全相同的結果:

set "FileToParse=%~1" 
set "OutputFile=%~2" 
set "NewExtension=%~3" 
for /F "usebackq tokens=* delims=" %%a in ("%FileToParse%") DO (
    set "line=%%a" 
    @setlocal ENABLEDELAYEDEXPANSION 
    set "line=!line:.wav=%NewExtension%!" 
    echo(!line!>>"%OutputFile%" 
    endlocal 
) 
+0

你能解釋一下如何通過啓用延遲擴展來擴展行嗎?當我在新的本地環境中指定%% a時,我不明白爲什麼字符串會被這樣裁剪。謝謝!而且代碼有點複雜,因爲它只是一個腳本的剪輯,我需要它作爲子例程。馬丁 – CmdQuestion 2013-03-10 12:43:39

+0

幹得好!非常感謝。馬丁 – CmdQuestion 2013-03-10 14:33:30