Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/batch-file/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Cmd SETLOCAL和ENABLEDELAYEDEXPANSION如何工作?_Cmd_Batch File - Fatal编程技术网

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中,并且从未关闭过它。我不会在默认情况下为系统启用它,因为您永远不知道系统是否运行批处理脚本,或者其他公司的批处理脚本是否与之冲突。这是我们的窗户