【问题标题】:Batch File: Prevent literal interpretation in a for /f loop批处理文件:防止 for /f 循环中的文字解释
【发布时间】:2013-10-30 13:22:59
【问题描述】:

目前我有一个循环遍历项目列表并将它们复制到目录(存档)。但是,列表中的一项(在路径名中有一个全局变量)被解释为“字面意思”(作为文本而不是代码)。 我知道通常您可以通过 (^^) 转义该行以将其解释为代码而不是文本,但显然我在这里做错了,因为它不起作用...

my.list 中存在问题的项目(其中包含转义)是:

location\foo^^%date:~0,3%*.zip

我使用的代码是……

for /f "delims=" %%a in (my.list) do (
    echo "%%a"
)

回声

"location\foo^^%date:~0,3%*.zip"

代替

location\fooMON*.zip

任何帮助将不胜感激。

【问题讨论】:

  • call echo "%%a" 呢?

标签: windows for-loop batch-file cmd escaping


【解决方案1】:

您对何时需要转义字符感到困惑。

某些字符具有特殊含义(如您所描述的“代码”)。很多时候,您可以转义字符,使其被解释为文字(文本)而不是“代码”。

在 Windows CMD.EXE 中转义字符的最常用方法是在其前面加上一个 ^ 字符。有时一个字符串会被解析两次,这可能需要^^^ 的转义序列(或者在启用延迟扩展时处理! 时可能需要^^)。更多轮次的解析需要更多的^ 字符。它很快就会变得混乱,需要练习才能掌握它。

但你的情况完全不同 - 它不能通过转义来解决。你的 FOR 变量中有“代码”,你希望它被解释为这样。但相反,它被解释为文本。为了理解原因,您必须了解批处理解析的各个阶段发生的顺序。你可以参考How does the Windows Command Interpreter (CMD.EXE) parse scripts?,但这是相当高级的东西,需要时间消化。

这是一个粗略的概要,显示了何时发生各种类型的扩展。 (注意 - 这些步骤编号与链接答案的阶段编号不完全匹配)

1) 参数扩展——%1
2) 普通变量扩展 - %var%
3) 用于变量扩展 - %%A
4) 延迟变量扩展 - !var!
5) CALL 扩展 - 如果涉及 CALL,请重复步骤 1) 和 2)

您希望您的%date:~0,3% 字符串进行正常(百分比)扩展。您的 FOR 循环逐字读取文本行,没有任何扩展。解析器第一次看到您的“代码”是在第 3 步)当 %%a FOR 变量展开时。你可以看到这已经来不及了 %date:~0,3% 扩展你想要的方式。

您有两种选择来解决您的问题。但请注意 - 这些解决方案中的每一个都可能会添加可能需要解决的新问题。

我假设^^ 是您试图强制扩展嵌入式“代码”的天真尝试。 ^^ 应该从您的列表文件中删除。

选项 1:使用 CALL 添加额外一轮正常扩展

for /f "delims=" %%a in (my.list) do call echo "%%a"

但是现在你有一个潜在的问题,你可能在你的列表中有一个% 文字,你确实想要被扩展。批处理脚本中的百分比不能用^ 转义。相反,您可以通过将其加倍为%% 来逃避一个百分比。因此,如果您的列表中有百分比文字,则它们必须加倍。

请注意,随问题发布的原始代码要复杂得多。它包括一个引用%%a 的IF 语句。您不能 CALL IF 或 FOR 命令。解决方法是调用一个子程序,传值,在子程序中包含复杂的逻辑。

for /f "delims=" %%a in (my.list) do call :processValue "%%a" >>Logs\xfer.log
exit /b

:processValue
echo Attempting to archive %1...
if exist "c:\%~1" (
  echo f | xcopy "c:\%%a" "c:\Lucas\archive\%~1" /E /C /H /R /Y
  if %errorlevel%==0 (
    echo ...%1 added to archive for transfer
    echo.
  ) else (
    echo ERROR: %1 not added to archive
    echo.
  )
) else (
  echo ERROR: %1 Not found on client computer
  echo.
)

选项 2:使用延迟扩展

启用延迟扩展,并将您的列表更改为使用 !date:~0,3! 而不是 %date:~0,3%。 FOR变量扩展后出现延迟扩展,所以会正常扩展。

setlocal enableDelayedExpansion
for /f "delims=" %%a in (my.list) do echo "%%a"

但是现在你有一个潜在的问题,你可能在你的列表中有一个! 文字,你确实想要扩展。您可以通过将 ! 转义为 ^! 来保留 ! 文字。

【讨论】:

    猜你喜欢
    • 2023-04-08
    • 1970-01-01
    • 2019-05-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-07
    相关资源
    最近更新 更多