cmd并感叹号 - 第二部分 [英] Cmd and exclamation marks - Part II

查看:176
本文介绍了cmd并感叹号 - 第二部分的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我真的不知道为什么解析包含任何特殊字符包括惊叹号文本文件时,我的字符串替换程序的工作原理。我预计,延迟的变量扩充将关闭符号,百分号等特殊的含义,但反而会失败感叹号...

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆