Escopo variável em arquivos em lote


2

Eu acho que essa é uma pergunta sobre escopo variável. Estou tentando entender por que a variável% average% pode conter algo diferente de "0" quando a linha echo average before %average%é atingida.

Parece conter o valor da execução anterior através do loop. Ele também não é atualizado pelo seguinte set /ae, portanto, permanece o mesmo em echo average after %average%. A próxima execução ao redor do loop tem o valor correto da execução anterior - mas não desta vez.

@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

Respostas:


3

Eu ia postar isso como um comentário, mas o campo de resposta tem melhores controles de formatação.

O JdeBP está totalmente correto em sua resposta, mas algumas correções do seu código podem esclarecer as coisas, se você ainda não chegou à resposta (já que estou postando isso um mês depois).

Primeiro, mude setlocalpara setlocal EnableDelayedExpansion. Isso ativa a expansão atrasada.

Altere todas as suas variáveis ​​referenciadas com a %variable_name%sintaxe para !variable_name!aproveitar o recurso de expansão atrasada. Qualquer variável avaliada ou alterada em um loop for precisará ser referenciada dessa maneira para obter resultados corretos / esperados.

Por exemplo, esta linha no seu código:

echo "ping %pingtime%"

deve ser alterado para

echo "ping !pingtime!".

Há uma explicação bastante boa da expansão atrasada aqui, com exemplos para ilustrar exatamente o que está acontecendo.


2

Eu acho que essa é uma pergunta sobre escopo variável.

Não é, no entanto. Os scripts de comando não têm a noção de escopos para variáveis. O que você está encontrando é o conhecido e antigo problema 1 de substituição de variáveis em um comando composto que precede a parte desse comando composto que define a variável para um novo valor. Pode-se ver exatamente a mesma coisa ocorrendo com uma simples linha dupla:

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

A expansão da variável na segunda linha, que é um comando composto, ocorre quando o comando é analisado, o que ocorre antes que qualquer parte dele seja executada nos interpretadores de comando da Microsoft (e da IBM e, de fato, meu). Seu forcomando é um comando composto de várias linhas.

Microsoft de CMDter atrasado a expansão de variáveis , que não é habilitado por padrão e tem de se permitir (com a /v:onopção de linha de comando para o interpretador de comandos ou através da EnableDelayedExpansionopção ao setlocalcomando em um script de comando), para combater este:

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

O TCC da JP Software adota uma abordagem diferente e expande variáveis ​​em comandos compostos progressivamente, processando cada comando simples dentro do composto à medida que o atinge. Portanto, ele não expande os %A%exemplos anteriores até depois de executar o segundo setcomando.


1 O primeiro intérprete de comando a exibi-lo, se a memória servir, estava cmdno OS / 2 versão 1.0, lançado em 1987. Esse foi o primeiro intérprete de comando da Microsoft que suportava comandos compostos.


11
Obrigado por reservar um tempo para a extensa resposta. Não tenho certeza de que ação devo tomar - minha primeira linha já está definida. O que mais eu preciso fazer?
Paul
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.