Змінна сфера в пакетних файлах


2

Я думаю, що це питання про змінні області. Я намагаюся зрозуміти, чому змінна% average% може містити щось інше, ніж "0", коли рядок echo average before %average% досягнуто.

Здається, він містить значення попереднього прогону через цикл. Він також не оновлюється наступним 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

Відповіді:


3

Я збирався опублікувати це як коментар, але поле відповіді має краще управління форматуванням.

JdeBP цілком правильний у своїй відповіді, але деякі виправлення з вашого коду можуть прояснити речі, якщо ви ще не прийшли до відповіді (бачачи, як я надсилаю це через місяць).

По-перше, зміни setlocal до setlocal 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 Команда є однією командою, що складається з декількох рядків.

Microsoft CMD має затримка змінної розширення , яка не ввімкнена за умовчанням, і потрібно ввімкнути (з /v:on параметр командного рядка для інтерпретатора команд або через EnableDelayedExpansion опції setlocal в командному сценарії), щоб боротися з цим:

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

TCC програмного забезпечення JP приймає інший хід і поступово розширює змінні в складених командах, обробляючи кожну просту команду всередині з'єднання, коли вона досягає її. Так що не розширюється %A% у попередніх прикладах до тих пір, поки не виконано друге set команду.


1 Перший інтерпретатор команд, який демонстрував це, якщо пам'ять служить, був cmd в OS / 2 версії 1.0, випущеної в 1987 році. Це був перший інтерпретатор команд Microsoft, який підтримував складні команди.


1
Дякуємо, що знайшли час на широку відповідь. Я не впевнений, які дії я повинен зробити - моя перша лінія вже встановлена. Що ще потрібно робити?
Paul
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.