CMD和感叹号 - 第二部分(Cmd and exclamation marks - Part II

2019-07-21 06:34发布

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

码:

@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"

享受配料! 马丁

Answer 1:

那是因为你启用延迟扩容 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%!"

你会得到

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

代替

专题| <>〜\²³{[]}! “'''UAO @;:€$%/()= chars.flac?


编辑:延迟扩展控件时,在一份声明变量扩展。 在脚本中的关键语句是线

set "line=%%a"

该分配循环变量的值%%a到可变line 。 迟发扩张禁用的字面意义%%a分配,因为脚本解释器无法展开%%a在分析时。 但是,当您启用延迟扩展,砰变量是在执行时扩大,所以解释着眼于价值%%a并且展开!whatever! 在它之前的结果被分配给变量line

也许它会用一个例子更加清晰。 如果您添加一行

%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!然后停止。

您可以强制(percent-)变量与内部变量的扩张call命令,虽然。 一个命令call set "line=!line!" 第一扩展为call set "line=%foo% bar"在当前上下文中,然后call求值set "line=%foo% bar"在一个新的上下文,其中%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
)


文章来源: Cmd and exclamation marks - Part II