首页 > 解决方案 > cmd 批处理变量行为不直观

问题描述

我正在使用 Windows 10,通过命令提示符窗口运行批处理文件。

我可以让事情发挥作用,但我不知道为什么它会起作用,或者为什么我不能做某些事情:

set "file_list=a1 a2"
for %%a in (%file_list%) do (
    echo %%a.py
)

这段小代码有效。我可以建立在它之上,但是

Q1:我想将变量 %%a 更改为 %%filename...但这不起作用!我想知道是否可能保留了文件名,所以我尝试了 %%fname 。在这种情况下,我收到错误:

%fname was unexpected at this time.

我可以从命令行进行设置并使用描述性变量名称,但在循环时它似乎不起作用。(我是用上面的 %file_list% 变量做到的!)那么为什么我只能对循环变量使用单个字符呢?有什么办法吗?

Q1a。这让我认为循环索引变量与 set 命令中的变量是不同类型的变量。那是对的吗?如果是这样,是否有一个链接可以清楚简洁地解释差异?

Q2。我注意到循环索引变量是 %%a,而不是 a 或 %a 或 %a% 。我永远不会猜到这一点。我看过的网站刚刚说,这样做。但我看不出任何解释为什么,除了第一个百分比是逃避。好的。这并不能解释什么。它只是意味着“这就是你的做法”。当我使用百分号时的错误信息很有趣。

set "file_list=a1 a2"
for %a in (%file_list%) do (
    echo %a.py
)

"file_list) was unexpected at this time."

所以我可以模糊地看到,也许某些东西没有被正确地转义。为什么 %a 中的 % 需要转义,所以变成 %%a ?

标签: loopsbatch-filevariablescmd

解决方案


元变量必须for%(在命令提示符中)或%%(在批处理文件中)和单个字符(区分大小写的字母)组成,例如%aor %%a。您不能定义%filename%%filename
循环变量只存在于各自的for循环中。不要将此类循环变量与普通环境变量混淆%TEMP%,例如全局可用的环境变量。

有这些东西用%-signs 标记:

  1. %-escaping(仅适用于批处理文件),因此%%表示一个文字%-sign;
  2. 命令行参数/参数(显然仅适用于批处理文件),例如%1
  3. 立即展开环境变量*,如%TEMP%;
  4. for元变量,例如%a(在命令提示符中)或%%a(在批处理文件中),它们特定于for命令,因此它们不存在于相关循环上下文之外;

%-escaping (1.) 发生在扩展元变量 (4.) 之前,因此实际上该for命令接收一个循环变量,如%a.
然后环境变量(3.)在命令提示符和批处理文件中的处理方式不同:前者按字面意思保留未定义的变量,后者删除它们。
详细的解析规则可以在这篇文章中找到,微软(或IBM?)已经以这种方式实现了这些规则,以便能够区分不同的%事物,所以最后是他们的决定,因此你必须询问他们的确切原因……</p>


*) 还有一些类似延迟环境变量扩展的东西,但是它使用!-signs 来标记变量,比如!TEMP!,这是%在解析所有 -sign 表达式之后发生的事情。


推荐阅读