【问题标题】:How to properly escape multiline output plus FOR plus %PROGRAMFILES(X86)% plus pipe, when stored in variable存储在变量中时如何正确转义多行输出加 FOR 加 %PROGRAMFILES(X86)% 加管道
【发布时间】:2019-07-29 07:23:47
【问题描述】:

这是在 cmd 中工作的:

 "C:\Program Files (x86)\CodeMeter\Runtime\bin\cmu32.exe" --list-content | FIND "Serial Number 12345-"

输出(从多行正确提取):

序列号为 12345-67890 和版本 1.19(锁定)的 CmContainer

但我想让它在 .bat 文件中工作并将结果存储到变量中(来自here):

 for /f "usebackq" %%i in (`"C:\Program^ Files^ ^(x86)\CodeMeter\Runtime\bin\cmu32.exe" --list-content ^| FIND "Serial Number 12345-"`) do SET foobar=%%i

它抛出:

文件名、目录名或卷标语法不正确。

PS:在最终版本中,我想使用系统变量作为路径,例如"%PROGRAMFILES(X86)%\CodeMeter\Runtime\bin\cmu32.exe",但是虽然这在 cmd 中没有什么区别,但它会抛出 "'C:\Program' is不被识别为内部或外部命令、可运行程序或批处理文件。” 从 .bat 中调用时...所以我猜有转义问题?

【问题讨论】:

  • 通常不需要转义除了|之外的任何东西,因为路径在保护特殊字符的""之间;然而,在这种情况下,第一个 " 和最后一个被视为一对,并在进一步处理之前被删除;为防止出现另一对但逃脱的对,所以... in ('^""%ProgramFiles(x86)%\..." ^| find "..."^"') ......
  • @aschipfl:'C:\Program' is not recognized as an internal or external command, operable program or batch file.。通过仅在第一个空格前添加 ^ 进行双重检查:'C:\Program Files' is not recognized as an internal or external command, operable program or batch file.
  • 同时编辑了我的第一条评论...
  • 更好,因为错误消息消失了。但是:结果仍然与命令行不一样,只是将- 存储在foobar 中......不过可能是一个不同的问题?

标签: batch-file cmd


【解决方案1】:

在你的命令行中:

for /f "usebackq" %%i in (`"C:\Program^ Files^ ^(x86)\CodeMeter\Runtime\bin\cmu32.exe" --list-content ^| FIND "Serial Number 12345-"`) do SET foobar=%%i

in 后面的表达式的第一个和最后一个引号被视为已删除的一对;然后处理余数,然后将其识别为错误语法。

为了防止在周围放置另一对退出标记,但要避开它们,如下所示:

for /f "usebackq" %%i in (`^""C:\Program Files (x86)\CodeMeter\Runtime\bin\cmu32.exe" --list-content ^| FIND "Serial Number 12345-"^"`) do SET foobar=%%i

这种奇怪行为的原因是for /F 使用cmd /S /c 运行in 后面的命令行,所以这就是使用您的代码执行的内容(没有任何转义):

cmd /S /c "C:\Program Files (x86)\CodeMeter\Runtime\bin\cmu32.exe" --list-content | FIND "Serial Number 12345-"

cmd /S 去掉第一个和最后一个 " 并留下以下行,这是无效的语法:

C:\Program Files (x86)\CodeMeter\Runtime\bin\cmu32.exe" --list-content | FIND "Serial Number 12345-

现在为了避免这种奇怪的余数,给cmd 一些明确的引号以删除:

cmd /S /c ""C:\Program Files (x86)\CodeMeter\Runtime\bin\cmu32.exe" --list-content | FIND "Serial Number 12345-""

我建议的转义是为了让命令路径(包括))出现在一对引号之间,以便不必关心任何进一步的转义(如^)):

cmd /S /c ^""C:\Program Files (x86)\CodeMeter\Runtime\bin\cmu32.exe" --list-content | FIND "Serial Number 12345-"^"

您不需要usebackq 选项,但您可能需要delims= 才能不在空格处拆分接收到的字符串,如下所示:

for /f "delims=" %%i in ('^""%ProgramFiles(x86)%\CodeMeter\Runtime\bin\cmu32.exe" --list-content ^| FIND "Serial Number 12345-"^"') do SET "foobar=%%i"

【讨论】:

  • 确实需要usebackq,得到The system cannot find the file ""C:\Program.`(注意双引号),但delims 成功了。谢谢!
  • 好吧,usebackq 不会改变这里对双引号的处理,它只是让你使用 ` 而不是 '...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-11-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-01
相关资源
最近更新 更多