Cmd SETLOCAL和ENABLEDELAYEDEXPANSION如何工作?
我注意到,在大多数脚本中,这两个脚本通常位于同一行:Cmd SETLOCAL和ENABLEDELAYEDEXPANSION如何工作?,cmd,batch-file,Cmd,Batch File,我注意到,在大多数脚本中,这两个脚本通常位于同一行: SETLOCAL ENABLEDELAYEDEXPANSION 这两个命令实际上是独立的,可以写在不同的行上吗 如果在脚本的第一行设置了ENABLEDELAYEDEXPANSION,并且直到脚本结束时才禁用,那么设置ENABLEDELAYEDEXPANSION会对脚本产生不利影响吗?ENABLEDELAYEDEXPANSION是传递给SETLOCAL命令的参数(查看SETLOCAL/?) 其效果在脚本或ENDLOCAL期间有效: 当到达批处
SETLOCAL ENABLEDELAYEDEXPANSION
这两个命令实际上是独立的,可以写在不同的行上吗
如果在脚本的第一行设置了
ENABLEDELAYEDEXPANSION
,并且直到脚本结束时才禁用,那么设置ENABLEDELAYEDEXPANSION
会对脚本产生不利影响吗?ENABLEDELAYEDEXPANSION
是传递给SETLOCAL
命令的参数(查看SETLOCAL/?
)
其效果在脚本或ENDLOCAL
期间有效:
当到达批处理脚本的末尾时,将显示一个隐含的ENDLOCAL
针对该批发出的任何未完成的SETLOCAL
命令执行
剧本
特别是,这意味着如果在脚本中使用
SETLOCAL ENABLEDELAYEDEXPANSION
,除非在某些使用延迟扩展的程序中需要使用ENABLEDELAYEDEXPANSION部分,即,它接受在IF或FOR命令中修改的变量的值,这些变量的名称用感叹号括起来
如果在不需要此扩展的脚本中启用此扩展,则仅当脚本中包含以感叹号括起的名称时,脚本的行为才会有所不同!喜欢这些通常只是删除名称,但如果碰巧存在同名的变量,则结果是不可预测的,取决于该变量的值及其出现的位置
SETLOCAL部分仅在一些专用(递归)程序中是必需的,但通常在您希望确保不会偶然修改任何具有相同名称的现有变量,或者希望自动删除程序中使用的所有变量时使用。但是,由于没有单独的命令来启用延迟扩展,因此需要此命令的程序还必须包括SETLOCAL部分。我认为您应该了解延迟扩展是什么。现有的答案无法(充分)解释这一点 键入
SET/?
可以很好地解释这件事:
延迟的环境变量扩展有助于
当一行
文本被读取,而不是在执行时读取。下面的例子
演示立即变量展开的问题:
set VAR=before
if "%VAR%" == "before" (
set VAR=after
if "%VAR%" == "after" @echo If you see this, it worked
)
将永远不会显示该消息,因为两个IF语句中都有%VAR%
在读取第一个IF语句时被替换,因为它在逻辑上
包括IF的主体,它是一个复合语句。所以如果
在复合语句中,实际上是将“before”与
“之后”永远不会相等。类似地,下面的示例
无法按预期工作:
set LIST=
for %i in (*) do set LIST=%LIST% %i
echo %LIST%
因为它不会在当前目录中建立文件列表,
而是将LIST变量设置为找到的最后一个文件。
同样,这是因为%LIST%在
语句,此时列表变量为空。所以
我们正在执行的实际FOR循环是:
for %i in (*) do set LIST= %i
它只是将列表设置为最后找到的文件
延迟环境变量扩展允许您使用不同的
字符(感叹号)以在以下位置展开环境变量:
执行时间。如果启用延迟变量扩展,则上述
可以编写如下示例以按预期工作:
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替换
如果没有setlocalenabledelayedexpansion
,感叹号就是这样,所以它会回显!b:1=2代码>两次
由于正常的环境变量在读取(block)语句时会展开,因此展开%b:1=2%
使用循环之前b
的值:z2
(但未设置时y2
。一个真正的问题经常存在,因为批处理文件完成后,内部设置的任何变量都不会导出。因此,它不可能出口,这导致了美国的问题。因此,我只是将注册表设置为始终使用延迟扩展(我不知道为什么它不是默认值,可能是速度或旧版兼容性问题。)问题的第二部分如何?如果启用它,它只会产生不利影响,然后编写了一些行为不同的代码(如果不是On),不幸的是,如果不调用setlocal,似乎无法启用延迟扩展,即使这些控制应该是独立的功能:-我想Alex K已经回答了这一部分:ENDLOCAL
被省略,因为当我们到达终点时,SETLOCAL
停止工作。我们程序员只是喜欢保持简短。。。使用EnableDelayedExpansion,如果文本只包含一个,您甚至会遇到问题代码>像回声你好代码>行中有一个感叹号,您也遇到了插入符号的问题回显“插入符号^”消失了代码>我通常将该行放在几乎所有脚本的顶部,它很少引起问题,而且我更喜欢它处理转义字符的方式,尤其是在解析XML或HTML时。@djangofan您考虑过使用AutoIt执行此类任务吗?强烈推荐。我已经从batch/powershell/vbscript迁移到AutoIt。是的,我听说过。也许我会仔细看看。我不喜欢要求第三方的东西,虽然。。。如果是这样的话,我似乎也可以使用Powershell。还有一个“SETLOCAL ENABLEEXTENSIONS”选项,但我不记得它有什么效果。多年来,我一直在使用批处理文件,我已经自动将该指令添加到每个em中,并且从未关闭过它。我不会在默认情况下为系统启用它,因为您永远不知道系统是否运行批处理脚本,或者其他公司的批处理脚本是否与之冲突。这是我们的窗户