windows - 为什么在这种情况下批处理文件中的延迟扩展不起作用?

标签 windows batch-file

这段代码

@echo off
setlocal EnableDelayedExpansion

set myvar=first
set first=second

echo myvar:!myvar!
set myvar=!myvar!
echo myvar:!myvar!

给予

myvar:first
myvar:first

在 Windows Vista SP2 上。

我期望的输出是

myvar:first
myvar:second

为什么会有差异,如何达到预期的效果?

最佳答案

问题是 set myvar=!myvar! 扩展为 set myvar=first,
你用相同的内容设置它,然后你要求 echo myvar:!myvar! 显示 myvar 的内容。

我会尝试添加更多解释,即使 Aacini 和 shf301 已经回答了这个问题。

两者都显示了使用 !%var%! 构造的双重扩展,Aacini 解释了为什么它可以工作,以及为什么反向版本 %!var!% 可以'工作。

恕我直言,有四种不同的扩展。
延迟扩张:
正如 Aacini 所解释的那样,延迟扩展对于内容中的任何特殊字符都是安全的(它可以处理从 0x01 到 0xFF 的所有字符)。

膨胀百分比:
百分比扩展无法处理或删除某些字符(即使转义)。
它对于简单的内容很有用,因为它可以在 endlocal 屏障之后扩展变量。

setlocal
set "myVar=simple content"
(
endlocal
set result=%myVar%
)

FOR 循环参数扩展:
这是安全的,如果延迟扩展被禁用,否则延迟扩展阶段在 %%a 变量扩展之后执行。
它很有用,因为它可以在 endlocal 屏障之后扩展变量

setlocal EnableDelayedExpansion
set "var=complex content &<>!"
for /F "delims=" %%A in ("!var!") DO (
  endlocal
  set "result=%%A"
)

SET 扩展:
set var 也扩展了一个变量,它始终是安全的并且独立于延迟扩展模式工作。

Aacini 刚刚解释了call %%%var%%% 构造是如何工作的,我只想给出一些额外的评论。
call 是可堆叠的,您可以使用其中的许多调用,并且每次调用都会重新启动解析器。

set "var=%%var%%#"
call call call call call echo %var%

结果为 %var%######

但是调用有很多缺点/副作用!
每次调用都加倍所有插入符号 ^
你可以说:“嘿,我已经测试过了,我看不到任何加倍”

call call call call echo ^^

结果 ^

尽管如此,但它大部分是隐藏的,因为每次重新启动也有一个特殊的字符阶段,其中插入符转义下一个字符,但您可以看到加倍效果

call call call call echo "^^"^^

结果 "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"^

即使调用扩展重新启动解析器,您也永远不能在任何阶段(仅在第一个阶段)使用延迟扩展。

如果检测到未转义的特殊字符,

call 将停止工作。

echo you ^& me
call echo you & me
call echo you ^& me
call echo you ^^& me
call echo you ^^^& me

只有第一个结果输出you & me,其他的都失败了。

另一个问题是调用非常慢,call var=contentset var=content 慢 ~50 倍,原因是 call tr​​y to start一个外部程序。

@echo off
setlocal
(
   echo echo *** External batch, parameters are '%%*'
) > set.bat
set "var="
call set var=hello
set var

我希望它有点有趣......
如果您想更深入地了解,可以阅读 CALL me, or better avoid call
How does the Windows Command Interpreter (CMD.EXE) parse scripts?

关于windows - 为什么在这种情况下批处理文件中的延迟扩展不起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7882395/

相关文章:

c++ - 创建指向特殊文件夹(如控制面板或计算机管理)的快捷方式

c - 为什么 scanf 会用 0 覆盖之前读取的 unsigned char 变量?

Windows Batch 根据文件名创建文件夹

Linux 和虚拟机

string - 批量 - 获取当前运行系统的系统语言

windows - 在 Windows Caffe 上训练 cifar10 时出现 libprotobuf 错误

windows - 使用批处理文件在 .txt 文件中搜索双字

batch-file - 想要使用VBScript在其他文件夹中运行.bat文件

JAVA,批处理文件错误

windows - 标题名称中的 taskkill 窗口空格