我已经将更复杂的CMD脚本削减到要领。它逐行读取输入文件,取消引用它(如果引用)并将其写入另一个CMD文件。
问题在于,如果输入文件中包含感叹号(!或bang),则该字符会在该行的某处被剥离。
这是CMD脚本,BANG1.CMD:
@echo off
setlocal ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
if exist bang2.cmd del bang2.cmd
for /f "tokens=*" %%a in (bang1.txt) do call :doit1 %%a
exit /b
:doit1
set P1=%1
if %P1%. EQU . exit /b
call :unquotex P1 %P1%
echo>>bang2.cmd echo P1:[%P1%]
exit /b
:unquotex
set X=%2
set Q=%X:~0,1%
if "!Q!" EQU ^""" SET X=!X:~1,-1!
set %1=%X%
exit /b
这是输入文件BANG1.TXT:
HelloWorld
"Hello World"
Hello!World
"Hello!World"
生成的文件BANG2.CMD最终包含:
echo P1:[HelloWorld]
echo P1:[Hello World]
echo P1:[HelloWorld]
echo P1:[HelloWorld]
问题是,嵌入式刘海发生了什么?我曾尝试使用和不使用ENABLEDELAYEDEXPANSION。我甚至尝试在输入文件中转义(^)刘海,仍然没有运气。
有没有办法保护它们?
感谢。
答案 0 :(得分:3)
问题在于延迟扩展。
对于延迟扩展,感叹号用于扩展变量,但当一行中只有一个感叹号时,它将被删除。
特别是在FOR / F循环中,延迟扩展很难处理,因为FOR参数的扩展直接受延迟扩展的影响。唯一的解决方案是暂时禁用它
下一个问题是CALL
,您无法使用CALL
传输内容(不会销毁它)。
最好通过引用传递变量(仅变量名),然后获取被调用函数中的内容。
代码中的最后一个问题是扩展百分比,不要使用它们
启用延迟扩展时,由于在扩展百分比之后评估延迟扩展,扩展线将通过延迟扩展第二次扩展。
样品。
假设var的内容为Bang!
echo %var%
扩展为Bang!
,但延迟展开会将Bang!
评估为Bang
。
使用echo !var!
,您只需获得Bang!
@echo off
setlocal ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
if exist bang2.cmd del bang2.cmd
for /f "tokens=*" %%a in (bang1.txt) do (
setlocal DisableDelayedExpansion
set "line=%%a"
setlocal EnableDelayedExpansion
call :doit1 line
endlocal
endlocal
)
exit /b
:doit1
set "P1=!%1!"
if "!P1!" EQU "" exit /b
call :unquotex P1
echo>>bang2.cmd echo P1:[!P1!]
exit /b
:unquotex
set "param=!%~1!"
if "!param:~0,1!" == ^""" (
set "param=!param:~1,-1!"
)
set "%1=!param!"
exit /b
答案 1 :(得分:2)
像这样:
@echo off
(for /f "delims=" %%a in ('type bang1.txt') do echo echo P1:[%%~a])>bang2.cmd
答案 2 :(得分:1)
试试这个:
@echo off
if exist bang2.cmd del bang2.cmd
for /f "tokens=*" %%a in (bang1.txt) do call :doit1 %%a
exit /b
:doit1
set "P1=%1"
if %P1%.==. exit /b
call :unquotex P1 %P1%
echo>>bang2.cmd echo P1:[%P1%]
exit /b
:unquotex
set "%1=%~2"
exit /b
使用参数,您可以使用%~1
而不是%1
来获取不带引号的版本。如果%1
包含"hello world"
,则%~1包含hello world
。这样可以实现更简单的不引用机制,从而无需延迟扩展。