批处理文件中的变量范围

批处理文件中的变量范围

我认为这是一个关于变量范围的问题。我试图理解为什么当echo average before %average%到达该行时 %average% 变量可以包含除“0”以外的任何内容。

它似乎包含上一次循环中的值。它也不会被后续循环更新,set /a因此在 中保持不变echo average after %average%。下一次循环运行时,它具有上一次运行的正确值 - 但这次不是。

@echo off
setlocal
set count=1
set four=0
set ping1=0
set ping2=0
set ping3=0
set ping4=0
set average=0
:loop
set pingtime=
set striptime=
@for /f "tokens=3 delims=="    %%G in ('ping -n 1 8.8.8.8 ^| find "Reply from"') do set pingtime=%%G
rem set pingtime=time=100ms
echo "ping %pingtime%"    
if "%pingtime%"=="" (
    set striptime=6666
) else (
rem    set striptime=%pingtime:~5,6%
rem    echo "Strip1 %striptime%"    
    set striptime=%pingtime:ms TTL=%
    echo Strip2=%striptime%
)
set ping%count%=%striptime%
@echo ping%count% time=%striptime%

echo %ping1% %ping2% %ping3% %ping4%    
set /a count+=1
if %count%==5 (
    set count=1
    set four=1
)
rem echo "Four= %four%"
if %four%==1 (
    set average=0
    echo average before=%average%
    echo %ping1% %ping2% %ping3% %ping4%    
    set /a average=%ping1%+%ping2%+%ping3%+%ping4%
    echo average after=%average%
    if %average% GTR 2500 (
     set four=0
         set ping1=0
         set ping2=0
         set ping3=0
         set ping4=0
     rasdial nextgdu /disconnect
     rasdial nextgdu
     rem | choice /c:ab /t:A,2 > NUL
    )
)
goto loop

答案1

我本来想将其作为评论发布,但答案栏有更好的格式控制。

JdeBP 的回答完全正确,但是如果您还没有找到答案的话,对您的代码进行一些修正可能会澄清一些事情(因为我是在一个月后发布这个问题的)。

首先,更改setlocalsetlocal EnableDelayedExpansion。这将启用延迟扩展。

%variable_name%然后使用语法将引用的所有变量更改!variable_name!为利用延迟扩展功能。在 for 循环中评估或更改的任何变量都需要以这种方式引用才能获得正确/预期的结果。

例如,您的代码中的这一行:

echo "ping %pingtime%"

应改为

echo "ping !pingtime!"

对于扩张延迟有一个很好的解释这里用例子来准确说明正在发生的事情。

答案2

我认为这是一个关于变量范围的问题。

但事实并非如此。命令脚本没有作用域变量。你遇到的是众所周知的、已有数十年历史的1问题变量替换在一个复合命令位于该复合命令中将变量设置为新值的部分之前。 我们可以用简单的两行代码看到完全相同的事情:

set A=ONE
set A=TWO & echo %A%

第二行的变量扩展是复合命令,在命令被解析时发生,在其任何部分执行之前在 Microsoft(以及 IBM,实际上还有我的)的命令解释器中。您的for命令是一个多行复合命令。

微软CMD已经延迟变量扩展,默认情况下未启用,必须启用(使用/v:on命令解释器的命令行选项或通过命令脚本中的命令EnableDelayedExpansion选项),以解决这个问题:setlocal

set A=ONE
set A=TWO & echo !A!

JP Software 的 TCC%A%采取了不同的策略,并逐步扩展复合命令中的变量,在到达复合命令时处理每个简单命令。因此,在前面的示例中,它直到执行完第二条命令后才扩展set


1如果记忆不错的话,第一个展现这一点的命令解释器是cmd1987 年发布的 OS/2 1.0 版。这是微软第一个支持复合命令的命令解释器。

相关内容