Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

I think this is a question about variable scope. I am trying to understand why the %average% variable can contain anything other than "0" when the line echo average before %average% is reached.

It appears to contain the value from the previous run through the loop. It also does not get updated by the following set /a and so stays the same in echo average after %average%. The next run around the loop it has the correct value from the previous run - but not this time around.

@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
share|improve this question

2 Answers 2

up vote 2 down vote accepted

I was going to post this as a comment, but the answer field has better formatting controls.

JdeBP is entirely correct in his answer, but some corrections from your code might clarify things, if you haven't arrived at the answer already (seeing as I'm posting this a month later).

First, change setlocal to setlocal EnableDelayedExpansion. This turns on delayed expansion.

Then change all of your variables referenced with the %variable_name% syntax to !variable_name! to take advantage of the delayed expansion feature. Any variable that gets evaluated or changed within a for loop will need to be referenced in this way to get correct/expected results.

For example, this line in your code:

echo "ping %pingtime%"

should be changed to

echo "ping !pingtime!".

There is a fairly good explanation of delayed expansion here with examples to illustrate exactly what is going on.

share|improve this answer

I think this is a question about variable scope.

It isn't, though. Command scripts don't have the notion of scopes for variables. What you are encountering is the well known and decades-old1 problem of variable substitution in a compound command preceding the part of that compound command that sets the variable to a new value. One can see exactly the same thing occurring with a simple two-liner:

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

The variable expansion on the second line, which is a compound command, occurs when the command is parsed, which happens before any part of it is executed in Microsoft's (and IBM's, and indeed my) command interpreters. Your for command is one multiple line compound command.

Microsoft's CMD has delayed variable expansion, which isn't enabled by default and one has to enable (with the /v:on command-line option to the command interpreter or via the EnableDelayedExpansion option to the setlocal command in a command script), to combat this:

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

JP Software's TCC takes a different tack, and expands variables in compound commands progressively, processing each simple command within the compound as it reaches it. So it doesn't expand the %A% in the preceding examples until after it has executed the second set command.


1 The first command interpreter to exhibit this, if memory serves, was cmd in OS/2 version 1.0, released in 1987. This was Microsoft's first command interpreter that supported compound commands.

share|improve this answer
    
Thanks for taking the time for the extensive reply. I am not sure what action I should take - my first line is setlocal already. What else do I need to do? –  Paul Sep 28 '11 at 13:17

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.