我在编写批处理文件时遇到了一个“奇怪”(对我来说)的问题,希望有人能解释为什么它会做它做的事情......我有一个批处理文件构建了-建立一个中等复杂的命令行,我希望它在执行之前将它构建的内容回显到屏幕上,以便我可以检查它是否已正确构建。我可以通过其他方式完成此操作1,但出于各种原因,我尝试了以下形式:
for %%a in (echo "") do %%~a complicated-command-line-with-parameters
想法是它会运行 do
部分两次:一次与%%a
设置为 echo
(将命令显示到控制台)并一次将其设置为 ""
: 期望它实际上会执行命令(使用 %%~a
会去掉双引号,剩下的就是命令本身)。然而,虽然 echo
有效,但命令本身并未执行。
对于最小复制,从命令提示符运行以下命令:
C:\>for %a in (echo "") do %~a dir
C:\>echo dir
dir
C:\> dir
可以看出,它运行 echo
命令没问题,但是好像dir
前面的空格阻止它被执行。
但请注意,手动运行带有前导空格的命令是可以的:
C:\> dir
Volume in drive C is OS
Volume Serial Number is A8BD-F861
...
并且,它是否以某种方式试图运行命令 <space>dir
,那么它(可能)会提示缺少命令:
C:\>" dir"
'" dir"' is not recognized as an internal or external command,
operable program or batch file.
问题:%~a
之间的空格(这是一个空字符串)并且要运行的命令似乎导致整行被忽略...有人知道为什么吗?
注意:无论是从命令提示符(如上所述)还是从 .BAT
中运行都没有区别文件(将 %a
更改为 %%a
等)。要运行的命令是内置命令(例如上面的 dir
)还是独立程序也没有任何区别。
进一步证明是%~a
之间的空格导致问题的命令来 self 发现的“修复”:
C:\>for %a in ("echo " "") do %~adir
C:\>echo dir
dir
C:\>dir
Volume in drive C is OS
Volume Serial Number is A8BD-F861
...
通过在 "echo "
中添加“分隔符” for
中的字符串命令,并将其从 do
中删除子句 ( ...do %~adir
),该命令按我最初的预期工作(尽管我不喜欢命令前面没有空格)。
浏览 (somewhat daunting) top answer 后问题How does the Windows Command Interpreter (CMD.EXE) parse scripts?那SomethingDark有帮助地链接到,一个似乎有效的更清洁的替代方法是:
C:\>for %a in (echo call) do %~a dir
C:\>echo dir
dir
C:\>call dir
Volume in drive C is OS
Volume Serial Number is A8BD-F861
...
可能有一些惯用的情况需要额外的 call
可能会影响某些,但目前,它似乎按预期工作。
1 我可以把@echo on
就在批处理文件内的行之前,但这也会导致显示提示(例如 C:\MyDirectory\SubDir>
),这是我不想要的。另一个“标准回退”是复制该行并粘贴 echo
在第一个副本之前,但他们很容易失去同步!
最佳答案
SomethingDark 已经指出了解释。
这是一行的命令与参数标记拆分。
在您的情况下,命令 token 始终是 %~a
这将在稍后替换,但即使它为空,解析器也不会重新评估命令 token 。
通过您的修复,dir 命令始终是命令标记的一部分。
但是当回声作为前缀时,它仍然可以回显剩余部分。
关于windows - 来自 FOR 命令的奇怪行为,其中看似无害的空间。解释?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57625825/