为了账号安全,请及时绑定邮箱和手机立即绑定

SETLOCAL和ENABLEDELAYEDEXPANSION如何工作?

SETLOCAL和ENABLEDELAYEDEXPANSION如何工作?

月关宝盒 2019-10-30 10:02:29
我注意到在大多数脚本中,这两个脚本通常在同一行中:SETLOCAL ENABLEDELAYEDEXPANSION实际上这两个命令是分开的并且可以写在单独的行上吗?将设置ENABLEDELAYEDEXPANSION,如果它被设置在脚本的第一线,直到剧本到底要不要禁止对脚本产生不利影响?
查看完整描述

3 回答

?
跃然一笑

TA贡献1826条经验 获得超6个赞

ENABLEDELAYEDEXPANSION是传递给SETLOCAL命令的参数(请参阅setlocal /?)


它的效果在脚本或以下期间有效ENDLOCAL:


当到达批处理脚本的末尾时,将对该批处理脚本发出的ENDLOCAL所有未完成SETLOCAL命令执行一个隐式执行。


特别是,这意味着,如果SETLOCAL ENABLEDELAYEDEXPANSION在脚本中使用,除非采取特殊措施,否则所有环境变量更改都会在脚本末尾丢失。


查看完整回答
反对 回复 2019-10-30
?
胡子哥哥

TA贡献1825条经验 获得超6个赞

我认为您应该了解延迟扩展是什么。现有的答案不能(足够)解释恕我直言。


键入SET /?可以很好地说明问题:


延迟的环境变量扩展对于避免当前扩展的局限性很有用,当前扩展的局限性发生在读取一行文本而不是执行文本时。下面的示例演示了立即变量扩展的问题:


set VAR=before

if "%VAR%" == "before" (

    set VAR=after

    if "%VAR%" == "after" @echo If you see this, it worked

)

永远不会显示该消息,因为在读取第一个IF语句时,BOTH IF语句中的%VAR%被替换了,因为它在逻辑上包括IF的主体,它是一个复合语句。因此,复合语句中的IF实际上是将“ before”与“ after”进行比较,这将永远是不相等的。同样,以下示例将无法正常工作:


set LIST=

for %i in (*) do set LIST=%LIST% %i

echo %LIST%

因为它不会在当前目录中建立文件列表,而只是将LIST变量设置为找到的最后一个文件。同样,这是因为读取FOR语句时,%LIST%仅被扩展了一次,那时LIST变量为空。因此,我们正在执行的实际FOR循环为:


for %i in (*) do set LIST= %i

只是将LIST设置为找到的最后一个文件。


延迟的环境变量扩展使您可以在执行时使用其他字符(感叹号)来扩展环境变量。如果启用了延迟变量扩展,则可以按如下所示编写以上示例以按预期方式工作:


set VAR=before

if "%VAR%" == "before" (

    set VAR=after

    if "!VAR!" == "after" @echo If you see this, it worked

)


set LIST=

for %i in (*) do set LIST=!LIST! %i

echo %LIST%

另一个示例是此批处理文件:


@echo off

setlocal enabledelayedexpansion

set b=z1

for %%a in (x1 y1) do (

 set b=%%a

 echo !b:1=2!

)

打印x2和y2:每1被2代替。


没有setlocal enabledelayedexpansion,感叹号就是这样,它将产生!b:1=2!两次回声。


因为当是(块)语句正常扩展环境变量的读取,扩大%b:1=2%使用值b循环之前有:z2(但y2在未设置)。


查看完整回答
反对 回复 2019-10-30
?
宝慕林4294392

TA贡献2021条经验 获得超8个赞

在某些使用延迟扩展的程序中,需要ENABLEDELAYEDEXPANSION部分,也就是说,该程序通过在变量IF或FOR命令中通过将其名称括在感叹号中来获取变量的值。

如果在不需要此扩展名的脚本中启用此扩展名,则仅当该脚本包含用惊叹号!LIKE!括起来的名称时,该脚本的行为才会不同。!这些!。通常,名称只是被擦除,但是如果偶然存在具有相同名称的变量,则结果是不可预测的,并且取决于该变量的值及其出现的位置。

SETLOCAL部分仅在少数几个专门的(递归)程序中是必需的,但是当您希望确保不偶然修改任何具有相同名称的现有变量,或者如果您想自动删除在您的程序中使用的所有变量时,通常使用SETLOCAL部分程序。但是,由于没有单独的命令来启用延迟的扩展,因此需要此命令的程序还必须包含SETLOCAL部分。


查看完整回答
反对 回复 2019-10-30
  • 3 回答
  • 0 关注
  • 1036 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信