我已经将更复杂的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。我什至尝试转义(^)输入文件中的刘海,但还是没有运气。

有什么办法可以保存它们?

谢谢。

最佳答案

问题根本就在于这里的扩展延迟。
对于延迟的扩展,感叹号用于扩展变量,但是当一行中只有一个感叹号时,它将被删除。

特别是在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

10-07 18:28