cmd并感叹号 - 第二部分 [英] Cmd and exclamation marks - Part II
问题描述
我真的不知道为什么解析包含任何特殊字符包括惊叹号文本文件时,我的字符串替换程序的工作原理。我预计,延迟的变量扩充将关闭符号,百分号等特殊的含义,但反而会失败感叹号...
I'm really wondering why my string replacement procedure works when parsing text files containing any special characters including exclamation marks. I expected that delayed variable expansion would switch off special meaning of ampersand, percent sign etc. but will fail instead for exclamation marks...
code:
@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:
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:
OutputFile.txt:
This a test for parsing lines with special characters
Rock & Roll.flac
Rock & Roll!.flac
Special | < > ~ \ ²³ { [ ] } ! " ´ ' ` üäö @ ; : € $ % & / ( ) = ? chars.flac
修改/补充:
在1年半,我不得不再次使用该code片段。看到两个额外的例子处理毒字符。第一个临时启用再次推迟扩大(见Ansgars答案),第二个用呼叫
。双方将解析的非空的文件路径和名称,并在当前目录下,但没有尾随驱动器号和路径到当前目录。
After 1 1/2 years I had to use this code snippet again. See two additional examples handling poison chars. First one with temporary enabled delayed expansion again (see Ansgars answer), second one using CALL
. Both will parse path and name of non-empty files in and below current directory, but without trailing drive letter and path to current dir.
例#1(设置围护双引号!文件=文件...
和回声&GTFILE!;&GT ; ...
不是必需的):
Example #1 (Enclosing double quotes in set "File=!File..."
and echo "!FILE!">>...
are not required):
@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(速度较慢,需要封闭双引号):
Example #2 (slower, enclosing double quotes required):
@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
测试文件和文件夹:
Files and folders for testing:
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"
享受配料!马丁
推荐答案
这是因为启用延迟扩展的之后的 set行= %%一个
:
That's because you enable delayed expansion after set "line=%%a"
:
set "line=%%a"
@echo on & setlocal ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
set "line=!line:.wav=%NewExtension%!"
如果您启用推迟扩张之前的 的分配 %% A
:
If you enable delayed expansion before assigning %%a
:
@echo on & setlocal ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
set "line=%%a"
set "line=!line:.wav=%NewExtension%!"
您将获得
专题| &LT; >〜\\²³{[]}€$%&安培; /()=? chars.flac
Special | < > ~ \ ²³ { [ ] } € $ % & / ( ) = ? chars.flac
而不是
专题| &LT; >〜\\²³{[]}! '''UAO @;:?€$%&安培; /()= chars.flac
Special | < > ~ \ ²³ { [ ] } ! " ´ ' ` üäö @ ; : € $ % & / ( ) = ? chars.flac
编辑:延迟扩展控件时,在一份声明中变量被扩展。在脚本中的关键语句行
Delayed expansion controls when variables in a statement are expanded. The critical statement in your script is the line
set "line=%%a"
该循环变量 %% A
的值赋给变量行
。延迟扩展禁用的字面意义%% A
分配,因为脚本间preTER不能展开 %% A
在分析时。但是,当您启用延迟扩展,砰变量都在执行时扩大,因此国米preTER看的%%的价值
并展开任何!什么!
在之前的结果赋值给变量行
。
which assigns the value of the loop variable %%a
to the variable line
. With delayed expansion disabled the literal value of %%a
is assigned, because the script interpreter cannot expand %%a
at parse time. However, when you enable delayed expansion, bang-variables are expanded at execution time, so the interpreter looks at the value of %%a
and expands any !whatever!
in it before the result is assigned to the variable line
.
也许会用一个例子更加清晰。如果添加行
Perhaps it'll become clearer with an example. If you add a line
%富%!富!
到输入文件并定义在脚本变量
to the input file and define the variable in the script:
@echo on & setlocal ENABLEEXTENSIONS
set "foo=bar"
set "InFile=%~1"
...
当您启用推迟扩张的之后的 set行= %%一个
既不%富%
也不!富!
%% A 分配给变量之前展开
行
(跨preTER没有看到的一个%%
执行时间之前的值),所以你得到这样的输出:
When you enable delayed expansion after set "line=%%a"
neither %foo%
nor !foo!
are expanded before %%a
is assigned to the variable line
(the interpreter doesn't see the value of %%a
before execution time), so you get this output:
%富%!富!
当您启用推迟扩张的前的 set行= %%一个
跨preTER分配前将扩大邦变量结果到变量行
,所以你得到这样的输出:
When you enable delayed expansion before set "line=%%a"
the interpreter will expand bang-variables before assigning the result to the variable line
, so you get this output:
%富%吧
%富%
只会在解析时被扩展,而此时间preTER无法看到的实际值%%一个
,所以%富%
仍然是一个文字%富%
在这里。
%foo%
would only be expanded at parse time, at which point the interpreter cannot see the actual value of %%a
, so %foo%
remains a literal %foo%
here.
像设置进一步分配行=行:!.WAV =%NewExtension%
不影响变量里面刘海或百分号,因为扩张ISN ŧ传递的,也就是说,它转换!行!
到%富%吧
(或%富%!富!
),然后停止。
Further assignments like set "line=!line:.wav=%NewExtension%!"
don't affect bangs or percent signs inside a variable, because expansion isn't transitive, i.e. it translates !line!
to %foo% bar
(or %foo% !foo!
) and then stops.
您可以强制(百分比)变量的内部与呼叫
命令变量的扩张,虽然。一个命令调用集行=!行了!
首先扩展到调用集行=%富%吧
在目前情况下,再呼叫
的计算结果 set行=%富%吧
在新的背景下,其中%富%
被扩展为栏
一样,所以变量行
分配值吧吧
。
You can force the expansion of (percent-)variables inside variables with the call
command, though. A command call set "line=!line!"
first expands to call set "line=%foo% bar"
in the current context, and then call
evaluates set "line=%foo% bar"
in a new context where %foo%
is expanded to bar
as well, so the variable line
is assigned the value bar bar
.
正如一个侧面说明:您code是太复杂了。你会得到同样的结果与此:
Just as a side note: your code is way too complicated. You'd get the exact same results with this:
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
)
这篇关于cmd并感叹号 - 第二部分的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!