CMD文件中缺少感叹号的奇怪情况 [英] The curious case of the missing exclamation mark in CMD files

查看:77
本文介绍了CMD文件中缺少感叹号的奇怪情况的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已将更复杂的CMD脚本缩减为基本要素.它将逐行读取输入文件,将其取消引用(如果已引用),然后将其写到另一个CMD文件中.

I have whittled down a more complex CMD script to the essentials. It reads an input file line by line, unquotes it (if quoted) and writes it out to another CMD file.

问题在于,如果输入文件中包含感叹号(!或bang),则该字符会沿该行的某个位置被剥离.

The problem is that if the input file contains exclamation marks (! or bang) the character gets stripped out somewhere along the line.

这是CMD脚本BANG1.CMD:

Here is the CMD script, 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:

Here is the input file BANG1.TXT:

HelloWorld
"Hello World"
Hello!World
"Hello!World"

生成的文件BANG2.CMD最终包含以下内容:

The resulting file BANG2.CMD ends up containing this:

echo P1:[HelloWorld]
echo P1:[Hello World]
echo P1:[HelloWorld]
echo P1:[HelloWorld]

问题是,嵌入的刘海怎么了?我尝试了是否启用ENABLEDELAYEDEXPANSION.我什至试过转义(^)输入文件中的刘海,仍然没有运气.

The question is, what happened to the embedded bangs? I have tried with and without ENABLEDELAYEDEXPANSION. I have even tried escaping (^) the bangs in the input file, still with no luck.

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

Is there any way to preserve them?

谢谢.

推荐答案

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

The problem at all is delayed expansion here.
With delayed expansion, exclamation marks are used to expand variables, but when there is only one exclamation mark in a line it will be removed.

特别是在FOR/F循环中,延迟扩展很难处理,因为FOR参数的扩展直接受到延迟扩展的影响.唯一的解决方案是暂时禁用它.
下一个问题是 CALL ,您不能使用 CALL 传输内容(而不会销毁它).
最好通过引用(仅变量名)传递变量,然后在调用的函数中获取内容.
代码中的最后一个问题是扩展百分比,请勿使用

Specially in FOR /F loops delayed expansion is tricky to handle, as the expansion of the FOR parameter is directly affected by the delayed expansion. The only solution is to disable it temporarily.
The next problem is the CALL, you can't transfer content with CALL (without destroying it).
It's better to transfer the variable by reference (only the variable name) and then get the content in the called function.
The last problem in your code are the percent expansions, do not use them

启用延迟扩展后,由于延迟扩展是在百分比扩展后评估的,因此扩展行将通过延迟扩展进行第二次扩展.
样本.假设var的内容是 Bang!

when delayed expansion is enabled, as the delayed expansion is evaluated after the percent expansion an expanded line will be expanded a second time by the delayed expansion.
Sample. Assume the content of var is Bang!

echo%var%扩展为 Bang!,但延迟的扩展将把 Bang!评估为 Bang

echo %var% expands to Bang! but then the delayed expansion will evaluate Bang! to 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

这篇关于CMD文件中缺少感叹号的奇怪情况的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆