【问题标题】:Batch script - usage of FOR /F with spaces in command and usebackq批处理脚本 - FOR /F 在命令和 usebackq 中使用空格
【发布时间】:2020-07-18 19:29:28
【问题描述】:

批处理脚本的新手。我需要将命令的输出分配给变量。我开始了解 FOR /F 命令。我的命令有空格和双引号。所以我尝试使用 usebackq 选项。但它因空间错误而失败。

for /F "usebackq delims=" %%G IN (`"C:\Program Files (x86)\ABC\DEF\XYZ.exe" Get /a "P1=D2" /b "Q1=D3" /c "D5"`) DO (
SET var=%%G
)

ECHO %var%

pause

失败:

'C:\Program' is not recognized as an internal or external command,
operable program or batch file.

根据 StackOverflow 上的其他问题,我做的一切都是正确的 - usebackq 用于使用反引号,demlims= 用于忽略空格作为分隔符。我不确定为什么它仍然失败。任何帮助表示赞赏!

【问题讨论】:

  • D:\Program 中的 D 是否实际上在输出中,或者这是一个错字,它真的是 C
  • UseBackQ 在那种情况下也根本不需要,所以删除它并恢复到标准的' 命令引用样式。
  • 抱歉是 C: - 现在更新了。
  • 大概是这样的:For /F "Delims=" %%G In ('^""%ProgramFiles(x86)%\ABC\DEF\XYZ.exe" Get /a "P1=D2" /b "Q1=D3" /c "D5"^"') Do Set "var=%%G"

标签: windows batch-file


【解决方案1】:

'` 中使用usebackq 的命令行由FOR 执行,带有选项/F 分别是Windows 命令进程cmd.exe 在后台处理批处理文件带有%ComSpec% /c 和作为附加参数附加的命令行。

ComSpec 是一个以%SystemRoot%\System32\cmd.exe 作为system 环境变量预定义的Windows 环境变量。

在命令提示符窗口中运行cmd /? 的帮助输出解释了在选项/C(执行命令行并关闭)或选项/K(执行命令行并继续运行)之后Windows 命令处理器如何解释字符串)。

这里不需要使用反引号,因为要执行的命令行本身不包含一个或多个带有' 的参数。所以可以将命令行括在'中。

FORhow the Windows command interpreter parses a batch script执行的命令行必须考虑到,即FOR命令行在@解析处理后的样子987654337@ 处理可以在debugging the batch file 上看到的批处理文件,以及如何将命令行作为参数字符串传递给在后台执行的第二个cmd.exe 实例。

至少有以下两种解决方案。

for /F "delims=" %%G in ('^""%ProgramFiles(x86)%\ABC\DEF\XYZ.exe" Get /a "P1=D2" /b "Q1=D3" /c "D5"^"') do set "var=%%G"
for /F "delims=" %%G in ('""C:\Program Files (x86^)\ABC\DEF\XYZ.exe" Get /a "P1^=D2" /b "Q1^=D3" /c "D5""') do set "var=%%G"

Compo 建议的第一个解决方案是更简单的解决方案。整个命令行包含在" 中,在后台启动的cmd.exe 在处理和执行剩余的命令行之前将其删除。在命令行开头和结尾额外添加的"^ 转义,因为cmd.exe 处理批处理文件以解释为文字字符而不是参数字符串的开头/结尾。因此,两个转义的" 之间的参数字符串通常由处理FOR 命令行的cmd.exe 解释。

第二种解决方案更难理解。整个命令行也包含在" 中,因为cmd.exe 在后台启动。但是cmd.exe 处理批处理文件时双引号不会被转义,因此这个cmd.exe 实例现在将命令行解释为以下参数字符串的列表:

  1. ""
  2. C:\Program
  3. Files
  4. (x86
  5. )
  6. \ABC\DEF\XYZ.exe
  7. " Get /a "
  8. P1=D2
  9. " /b "
  10. Q1=D3
  11. " /c "
  12. D5
  13. ""

(x86 之后的右圆括号在这种情况下不会被解释为文字字符,因为在处理整个 FOR 命令行的 cmd.exe 的双引号参数字符串之外。出于这个原因,它必须用 ^ 转义,以解释为文字字符,而不是作为 set 的末尾放置在 ' 标记要执行的命令行结束之前的错误位置。

这两个等号都在cmd.exe 处理批处理文件的双引号参数字符串之外。因此cmd.exe 会将它们解释为参数分隔符,并将每个= 替换为空格字符。这里不需要这样做,因为参数应该作为P1=D2Q1=D3 传递给可执行文件,而不是P1 D2Q1 D3。因此,两个等号必须用^ 转义,才能解释为文字字符,而不是cmd.exe 处理批处理文件时的参数分隔符。

两种解决方案都导致在后台运行,Windows 安装到 C:\Windows,32 位程序文件安装到 C:\Program Files (x86)

C:\Windows\System32\cmd.exe /c ""C:\Program Files (x86)\ABC\DEF\XYZ.exe" Get /a "P1=D2" /b "Q1=D3" /c "D5""

后台命令进程删除第一个和最后一个"然后运行

"C:\Program Files (x86)\ABC\DEF\XYZ.exe" Get /a "P1=D2" /b "Q1=D3" /c "D5"

可以在目录C:\Program Files (x86)\ABC\DEF 中创建一个只包含命令行@echo %0 %* 的批处理文件XYZ.bat,并在包含FOR 的批处理文件中将.exe 替换为.bat命令行查看批处理文件是否完全执行以及将哪些参数传递给批处理文件。这有助于了解在命令提示符窗口中删除 @echo off 并使用 FOR 命令行运行批处理文件的情况。

【讨论】:

    【解决方案2】:

    由于程序名称​​后参数周围的附加引号,发布的行失败。一种解决方法是将整个命令行嵌入到另一对外引号中(并将保留字符(如 ())转义为 ^(^),因为它们现在位于引号字符串之外)。

    for /F "usebackq delims=" %%G IN (`""C:\Program Files ^(x86^)\ABC\DEF\XYZ.exe" Get /a "P1=D2" /b "Q1=D3" /c "D5""`) do (...)
    

    如评论中所述,在这种情况下实际上不需要usebackq,如果使用常规引号,则相同的语法将起作用。

    【讨论】:

      【解决方案3】:

      这里不需要使用反引号或usebackq,只需使用单引号字符串和双引号即可。

      @echo off
      for /F "delims=" %%G IN ('"C:\Program Files (x86)\ABC\DEF\XYZ.exe" Get /a "P1=D2" /b "Q1=D3" /c "D5"') do set "var=%%G"
      

      还请注意,不需要括号 do 代码块来设置变量,事实上,据我所知,您甚至不需要变量,因为您可以通过使用元变量来摆脱。

      @echo off
      set "prog=C:\Program Files (x86)\ABC\DEF\XYZ.exe"
      for /F "delims=" %%G IN ('"%prog%" Get /a "P1=D2" /b "Q1=D3" /c "D5"') do echo %%G
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-10-11
        • 2010-09-20
        • 1970-01-01
        • 2011-10-21
        • 2018-11-07
        • 2010-11-02
        相关资源
        最近更新 更多