CMD文件中缺少感叹号的奇怪案例

时间:2016-02-22 19:57:40

标签: windows batch-file cmd

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

有没有办法保护它们?

感谢。

3 个答案:

答案 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。这样可以实现更简单的不引用机制,从而无需延迟扩展。