我需要转义“!” (和其他特殊字符)在启用了延迟变量扩展的for循环中
我尝试用字符串替换^^手动转义循环变量!在循环变量%% a中却没有运气。 for读完它们已经为时已晚吗?如果是这样,我该怎么做到呢?
下面是一个简短函数。这里唯一相关的部分是for循环和echo语句。那就是从文件的第X行打印出整行,这些行是文件路径。它们(有时)包含“!”之类的字符。和其他麻烦的特殊字符。我只希望echo在这里传递它而不解释它-而是最终删除了我的“!”字符 就我的使用而言,它们必须完全正确或无用,因为它们以后必须与实际文件相关联以用于我的用途。
setlocal EnableDelayedExpansion
:SplitList
if [%3] == [] goto :SplitListUsage
set inputfile=%~1
set outputfile=%~2
set splitnumber=%~3
set skipLines=0
set skipLines=%~4
if %skipLines% GTR 0 (
set skip=skip=%skipLines%
) else (
set skip=
)
@echo off > %outputfile%
set lineNumber=0
for /f "tokens=* %skip% delims= " %%a in (%inputfile%) do (
set /a modulo="!lineNumber! %% !splitnumber!"
if "!modulo!" equ "0" (
echo %%a >> !outputfile!
)
set /a lineNumber+=1
)
exit /B 0
答案 0 :(得分:1)
快速解决方案:
if !modulo! equ 0 (
setlocal DisableDelayedExpansion
(echo %%a)>> "%outputfile%"
endlocal
)
更好的解决方案:
根据您的代码示例,无需为整个代码启用延迟扩展,
实际上,您应该禁用它,以免弄乱可能包含{{1的文件名或输入字符串}},并在必要时启用它:
!
注意事项:
您的代码中还有一些其他问题,您可能已经注意到,上述解决方案中的一些问题已得到纠正。但是为了不分散您的注意力,我在这里单独介绍了它们。
写入setlocal DisableDelayedExpansion
REM Rest of the code...
for /f "tokens=* %skip% delims= " %%a in (%inputfile%) do (
set /a "modulo=lineNumber %% splitnumber"
setlocal EnableDelayedExpansion
for %%m in (!modulo!) do (
endlocal
REM %%m is now have the value of modulo
if %%m equ 0 (
(echo %%a)>> "%outputfile%"
)
)
set /a lineNumber+=1
)
时,还有改进代码性能的空间。
这是重写的代码,涵盖了其余部分:
outputfile
@echo off
setlocal DisableDelayedExpansion
:SplitList
if "%~3"=="" goto :SplitListUsage
set "inputfile=%~1"
set "outputfile=%~2"
set "splitnumber=%~3"
set "skipLines=0"
set /a "skipLines=%~4 + 0" 2>nul
if %skipLines% GTR 0 (
set "skip=skip=%skipLines%"
) else (
set "skip="
)
set "lineNumber=0"
(
for /f "usebackq tokens=* %skip% delims= " %%a in ("%inputfile%") do (
set /a "modulo=lineNumber %% splitnumber"
setlocal EnableDelayedExpansion
for %%m in (!modulo!) do (
endlocal
REM %%m is now have the value of modulo
if %%m equ 0 echo(%%a
)
set /a lineNumber+=1
)
)>"%outputfile%"
保护变量分配,例如"
。如果现在裸露的批处理参数set inputfile=%~1
包含空格或特殊字符(如%~1
),则批处理文件将失败,可能是致命的语法错误,或者是执行时数据不正确。推荐的语法是使用&
,它不会将引号分配给变量值,但是可以防止特殊字符。它还可以保护分配以防意外尾随空格。set "var=value"
可能包含特殊字符或空格,因此在%inputfile%
的IN子句中使用时,应通过双引号对其进行保护。在FOR /F
中双引号时,还必须使用FOR /F
参数。usebackq
不需要扩展变量值:SET /A
。变量名称可以直接使用,无论延迟扩展与否都可以正确使用。set /a modulo="!lineNumber! %% !splitnumber!"
循环中使用(echo %%a) >> "%outputfile%"
会带来严重的性能损失,特别是在进行大量迭代时,因为在每次迭代时,输出文件都会被打开,写入然后关闭。提高性能整个FOR
循环可以重定向一次。任何新数据都将添加到已打开的文件中。FOR
用于防止空变量值或变量值为echo(
时。如果变量为空,则使用/?
可以显示“ ECHO is on / off”消息,或者可以显示回显用法帮助。echo %%a
而不是(echo %%a)>> "%outputfile%"
的原因是为了防止在echo %%a >> "%outputfile%"
和%%a
之间输出多余的空间。现在您知道了使用>>
的原因,很容易理解更安全的替代方法:echo(