Cmd*_*ion 3 windows cmd batch-file delayedvariableexpansion
我真的想知道为什么我的字符串替换过程在解析包含任何特殊字符(包括感叹号)的文本文件时有效.我预计延迟变量扩展会关闭&符号,百分号等的特殊含义,但会因感叹号而失败...
码:
@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
Run Code Online (Sandbox Code Playgroud)
InputFile.txt:
This a test for parsing lines with special characters
Rock & Roll.wav
Rock & Roll!.wav
Special | < > ~ \ ²³ { [ ] } ! " ´ ' ` üäö @ ; : € $ % & / ( ) = ? chars.wav
Run Code Online (Sandbox Code Playgroud)
命令行语法:
D:\Users\Public\Batch\YAET>parse.bat "InputFile.txt" "OutputFile.txt" ".flac"
Run Code Online (Sandbox Code Playgroud)
OutputFile.txt:
This a test for parsing lines with special characters
Rock & Roll.flac
Rock & Roll!.flac
Special | < > ~ \ ²³ { [ ] } ! " ´ ' ` üäö @ ; : € $ % & / ( ) = ? chars.flac
Run Code Online (Sandbox Code Playgroud)
编辑/补充:
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
Run Code Online (Sandbox Code Playgroud)
示例#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
Run Code Online (Sandbox Code Playgroud)
用于测试的文件和文件夹:
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
Run Code Online (Sandbox Code Playgroud)
输出:
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"
Run Code Online (Sandbox Code Playgroud)
享受批量!马丁
那是因为你启用延迟扩展后 set "line=%%a":
set "line=%%a"
@echo on & setlocal ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
set "line=!line:.wav=%NewExtension%!"
Run Code Online (Sandbox Code Playgroud)
如果在分配之前启用延迟扩展%%a:
@echo on & setlocal ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
set "line=%%a"
set "line=!line:.wav=%NewExtension%!"
Run Code Online (Sandbox Code Playgroud)
你会得到
特别| <>〜\²³{[]}€$%&/()=?chars.flac
代替
特别| <>〜\²³{[]}!"''üäö@;:€$%&/()=?chars.flac
编辑:延迟扩展控制何时扩展语句中的变量.脚本中的关键语句就是该行
set "line=%%a"
Run Code Online (Sandbox Code Playgroud)
它将循环变量的值赋给%%a变量line.禁用延迟扩展后,%%a将分配文字值,因为脚本解释器无法%%a在分析时扩展.但是,当您启用延迟扩展时,会在执行时扩展爆炸变量,因此解释器会在将结果分配给变量之前查看其值%%a并展开其中的任何!whatever!变量line.
一个例子也许会变得更加清晰.如果添加一行
%foo%!foo!
到输入文件并在脚本中定义变量:
@echo on & setlocal ENABLEEXTENSIONS
set "foo=bar"
set "InFile=%~1"
...
Run Code Online (Sandbox Code Playgroud)
如果在分配给变量之前既没有扩展也没有扩展之后 启用延迟扩展(解释器没有看到执行时间之前的值),那么你得到这个输出:set "line=%%a"%foo%!foo!%%aline%%a
%foo%!foo!
当您启用推迟扩张之前 set "line=%%a"的解释将扩大砰变量结果赋给变量之前line,所以你得到这样的输出:
%foo%bar
%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进行求值,因此为变量赋值.set "line=%foo% bar"%foo%barlinebar 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
)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
9762 次 |
| 最近记录: |