【问题标题】:CMD Setlocal EnableDelayedExpansion inside a For Loop not working as I'd LikeFor 循环内的 CMD Setlocal EnableDelayedExpansion 无法正常工作
【发布时间】:2018-04-16 04:58:36
【问题描述】:

我想创建一个批处理文件函数来查看服务器,看看我是否需要更新任何程序。我现在设置的方式在

for /l ...

我面临的问题是你需要在循环内部使用 !var!获取更新后的变量值。如果你使用 goto 函数作为 /l 的 sudo 绕过它,它可以工作

以下是无法正常工作的代码行

setlocal enabledelayedexpansion
...

Set LocalL1=Example1.exe
Set /a LocalL1.Byte=1234
...

Set Servr1L=Example2.exe
Set /a LocalL1.Byte=1234
...

FOR /L %%A IN (1,1,%ServrList.Count%) DO (
   Set Temp1=!%LocalL%%%A!
   Set Temp2=!%ServrL%%%A!
   Set Temp1=!!Temp1!.byte!
   Set Temp2=!!Temp2!.byte!
)

实际结果

FOR /L %%A IN (1,1,%ServrList.Count%) DO (
   Set Temp1=Example1.exe
   Set Temp2=Example2.exe
   Set Temp1=Example2.exe.byte
   Set Temp2=Example2.exe.byte
)

我希望它输出什么

FOR /L %%A IN (1,1,%ServrList.Count%) DO (
   Set Temp1=Example1.exe
   Set Temp2=Example2.exe
   Set Temp1=1234
   Set Temp2=1234
)

如果您需要更多代码,请告诉我,但我必须执行“!%LocalL%%%A!”让它工作。在 For /L 之外,它只是不想对每个都进行硬编码

【问题讨论】:

  • 也许如果您要透露您对这段代码的期望,我们就能提供解决方案。例子。您提供的代码中没有set 的变量的变量内容。您是否已验证变量的内容是否符合您的预期(除了您遇到问题的明显结果)
  • 验证变量是否已设置并添加我想要的代码输出
  • 如果我理解正确,你有一些我称之为嵌套变量的东西;请参阅this post 以了解如何扩展类似的内容...
  • 在您的FOR /L %%A ... 中使用Set Temp1=!LocalL%%A!,后跟FOR %%T IN (!Temp1!) DO Set Temp1=!%%T.byte!Temp2 也是如此(或者您也可以使用 another FOR /L 循环来改变 Temp# 中的索引 #)。这种 (array) 管理在上面 aschipfl 链接的答案中进行了解释...
  • 但是,您的预期结果是错误的。您的代码应该执行Set /a %LocalL1%.Byte=1234(与Set /a Example1.exe.Byte=1234 相同)以显示您的结果。我建议您仔细检查您要实现的目标...

标签: windows batch-file for-loop cmd


【解决方案1】:

这个批处理代码应该可以工作,虽然不清楚你真正想要什么:

@echo off
setlocal EnableExtensions EnableDelayedExpansion
rem ...

set "LocaleL1=Example1.exe"
set "LocaleL1.Byte=1234"
rem ...

set "ServerL1=Example2.exe"
set "ServerL1.Byte=4321"
rem ...

set "ServerList.Count=1"

for /L %%A in (1,1,%ServerList.Count%) do (
   set "MyLocaleLabel=!LocaleL%%A!"
   set "MyServerLabel=!ServerL%%A!"
   set "MyLocaleByte=!LocaleL%%A.Byte!"
   set "MyServerByte=!ServerL%%A.Byte!"
   set My
   echo/
)

endlocal

Windows 命令解释器首先在命令块循环执行期间用当前循环变量值替换%%A。然后执行 SET 并延迟环境变量扩展,从而将环境变量LocaleL1 的值分配给环境变量MyLocaleLabelServerL1 的值分配给MyServerLabelMyServerLabel 的值到MyLocaleByteServerL1.Byte 的值到MyServerByte

接下来输出名称中以My开头的四个环境变量的值。所以发布的批处理文件在命令提示符窗口中运行时输出:

MyLocaleByte=1234
MyLocaleLabel=Example1.exe
MyServerByte=4321
MyServerLabel=Example2.exe

我更改了所有环境变量名称,因为有问题的原始名称对我来说太混乱了。

提示:不要使用算术表达式为环境变量赋值。环境变量总是字符串类型。

在使用 set /a LocalL1.Byte=1234 的算术表达式时,Windows 命令解释器首先必须将具有十六进制字节 31 32 33 34 00 的字符串转换为具有值 1234 的 32 位有符号整数,并将四个十六进制字节 @ 保存在内存中987654340@(LSB 到 MSB),然后将整数转换回具有五个字节 31 32 33 34 00 的字符串。这没有多大意义,尽管完成得如此之快,以至于没有人会注意到与 set "LocalL1.Byte=1234" 在执行时间上的区别,在该时间上只执行一个简单的字符串副本(如果有的话)。

在命令提示符窗口中进一步运行set /?,并仔细阅读命令SET从第一页到最后一页的输出帮助。环境变量通常可以而且应该在算术表达式中仅通过名称引用,而不使用%!,即set /A TCount=TCount + 1 或更短的set /A TCount+=1。帮助解释了为什么这在算术表达式中有效,以及为什么这种语法更好。

要了解所使用的命令及其工作原理,请打开命令提示符窗口,在其中执行以下命令,并仔细阅读每个命令显示的所有帮助页面。

  • echo /?
  • endlocal /?
  • for /?
  • set /?
  • setlocal /?

我建议也阅读一下

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多