возврат var обратно в вызов командного файла

я запускаю пакетный файл для обработки некоторого кода, в то время как он вызывает другой пакетный файл и должен вернуть переменную, но методы, описанные в справочных страницах о local/endlocal, похоже, здесь не работают, что я делаю неправильно, пожалуйста?

первый пакетный файл:

@ECHO OFF
setlocal
call secondbatchfile.bat xyz
echo. [%val1%]

второй пакетный файл:

@if (@a==@b) @end /*                        <== btw what does this code do ???
@echo off
setlocal enabledelayedexpansion
set "URL=%~1"
set bla bla ...
do bla bla ...

for /f "delims=" %%I in ('cscript /nologo /e:jscript "%~f0" "%URL%"') do (

rem trim whitespace from beginning and end of line
for /f "tokens=*" %%x in ("%%~I") do set "line=%%x"

rem test that trimmed line matches "variable=number"
echo !line! | findstr /i "^to[a-z]*=[0-9]*" >NUL && (

rem test was successful.  Scrape number.
for /f "tokens=2 delims==" %%x in ("%%I") do set "val1=%%x"

echo !val1!                            <== this works
ENDLOCAL & SET top=%val1%              <== this not

)
)

это приводит к:

c:\test>firstbatchfile.bat
123456789                                   <== this works
 []                                         <== this not

я пробовал другой синтаксис возвращаемой переменной, такой как !val1! или %%val1 - ничего не работало. что мне не хватает?

ОБНОВЛЕНИЕ: относительно другого примера здесь на сайте я пробовал:

call seconbatchfile.bat xyz ret1
echo. [%2%] [%ret1%]

и во втором файле изменено:

rem ENDLOCAL & SET %2=!val1!

тоже не работает?

РЕШЕНИЕ:

второй пакетный файл может быть исходным скриптом из rojo, считывающим весь веб-сайт, я оставил строки синтаксиса обрезки и сопоставления, чтобы возвращать только соответствующие совпадения:

for /f "delims=" %%I in ('cscript /nologo /e:jscript "%~f0" "%URL%"') do (

rem trim whitespace from beginning and end of line
for /f "tokens=*" %%x in ("%%~I") do set "line=%%x"

rem test that trimmed line matches "variable=number"
echo !line! | findstr /i "^[a-z]*=[0-9]*" >NUL && (

echo(%%I

)
)

и первый пакетный файл, вызывающий его, выполнит поиск двух необходимых параметров, например:

@ECHO OFF
setlocal
for /f "delims=" %%I in ('secondbatchfile.bat "http://xyz"') do (

echo %%I | findstr /i "top" >NUL && (

for /f "tokens=2 delims==" %%x in ("%%I") do (
set "updir=%%x"
)
)
echo %%I | findstr /i "low" >NUL && (

for /f "tokens=2 delims==" %%x in ("%%I") do (
set "lowdir=%%x"
)
)
)

echo.[%updir%]
echo.[%lowdir%]

большое спасибо rojo за фантастический код


person peet    schedule 21.03.2013    source источник
comment
почему бы просто не установить переменную среды во внутреннем пакете? вот так set RETURNVALUE=your_value   -  person shibormot    schedule 22.03.2013
comment
Строка @if абсолютно ничего не делает, поскольку строка (@a никогда не может быть равна строке @b). Ведущий @ подавляет эхо-оператор на консоль для этого ОДНОГО оператора. Вероятно, его можно безопасно удалить, если только не используется какой-то действительно неясный метод, например, какая-то другая [пакетная?] Программа, пытающаяся найти эту строку в исходном файле .bat.   -  person Magoo    schedule 22.03.2013
comment
но он установлен во внутренней партии, не так ли? в третьей-последней строке do set val1=%%x - если я удалю фрагмент кода endlocal, результат также будет пустым при вызове пакета?   -  person peet    schedule 22.03.2013
comment
здесь @a   -  person peet    schedule 22.03.2013
comment
Питер прав, эта первая строка ничего не делает - в пакетном режиме, НО: команда FOR вызывает тот же самый файл (jscript %~f0), что и Java-Script. И Java интерпретирует /* как начало комментария (например, REM). В вашем скрипте должен быть */, чтобы указать EndComment - непосредственно перед запуском java-кода. Таким образом, вы можете использовать один и тот же файл как в пакетном режиме, так и в качестве сценария Java.   -  person Stephan    schedule 22.03.2013


Ответы (2)


Самое простое решение состоит в том, чтобы ваш второй пакетный файл повторил его результат и зафиксировал его с помощью цикла for в первом пакетном файле. Отмена вашего setlocal для передачи переменной среды обратно вызывающему сценарию - грязное дело.

первый.bat:

@echo off
setlocal

for %%x in (
    "http://10.0.0.1/foo/vars.txt"
    "http://10.0.0.1/bar/vars.txt"
    "http://10.0.0.1/baz/vars.txt"
    "http://10.0.0.1/qux/vars.txt"
    "http://10.0.0.1/corge/vars.txt"
) do (
    for /f "delims=" %%I in ('fetchvalue.bat "%%~x"') do (
        set "val1=%%I"
    )
    echo.[%val1%]
)

fetchvalue.bat:

@if (@a==@b) @end /*

:: fetchvalue.bat <url>
:: output the "value" part of variable=value from a text file served by http

@echo off
setlocal
if "%~1"=="" goto usage
echo "%~1" | findstr /i "https*://" >NUL || goto usage

set "URL=%~1"

for /f "delims=" %%I in ('cscript /nologo /e:jscript "%~f0" "%URL%"') do (

    rem trim whitespace from beginning and end of line
    for /f "tokens=*" %%x in ("%%~I") do set "line=%%x"

    rem test that trimmed line matches "variable=number"
    echo !line! | findstr /i "^to[a-z]*=[0-9]*" >NUL && (

        rem test was successful.  Scrape number.
        for /f "tokens=2 delims==" %%x in ("%%I") do echo(%%x
    )
)

goto :EOF

:usage
echo Usage: %~nx0 URL
echo     for example: %~nx0 http://www.google.com/
echo;
echo The URL must be fully qualified, including the http:// or https://
goto :EOF

JScript */
var x=new ActiveXObject("Microsoft.XMLHTTP");
x.open("GET",WSH.Arguments(0),true);
x.setRequestHeader('User-Agent','XMLHTTP/1.0');
x.send('');
while (x.readyState!=4) {WSH.Sleep(50)};
WSH.Echo(x.responseText);

Вот пример first.bat, который сортирует полученные значения, устанавливает low наименьшее значение, а high устанавливает наибольшее значение.

@echo off
setlocal enabledelayedexpansion

for %%x in (
    "http://10.0.0.1/foo/vars.txt"
    "http://10.0.0.1/bar/vars.txt"
    "http://10.0.0.1/baz/vars.txt"
    "http://10.0.0.1/qux/vars.txt"
    "http://10.0.0.1/corge/vars.txt"
) do (
    set low=
    for /f "delims=" %%I in ('fetchvalue.bat "%%~x" ^| sort') do (
        if not defined low set "low=%%I"
        set "high=%%I"
    )
    echo low: !low!
    echo high: !high!
)
person rojo    schedule 22.03.2013
comment
вау, так что в моем примере вверху мне нужно будет использовать %%I, чтобы поймать эхо-результат синтаксического анализа? мне нужна модульность, потому что первый файл выполняет цикл около 15 устройств и обрабатывает различные действия на всех из них. для одного из этих действий мне нужен результат вашего гениального http-скрипта. по крайней мере, мне нужно было бы иметь возможность вызывать его как функцию в первом скрипте, хотя я думал, что его будет легче читать, если не перегружать. как вызов функции был бы лучшим способом в ваших глазах? - person peet; 22.03.2013
comment
@peet - А, хорошо. Я взял комбинированный пример. Я также обновил пример first.bat, чтобы проиллюстрировать, как вы можете использовать цикл for для предоставления другому циклу for его URL. - person rojo; 22.03.2013
comment
Я правильно понял, что мне нужна функция, которая вызывает другой пакетный файл для использования возвращаемой переменной? Я попробовал ваш код, который работает для shure, так как мне нужны только две переменные из 10 доступных для поиска, которые я думал удвоить, по одной для каждого искомого (необходимого) значения сверху и снизу. есть ли еще одна простая функция для разумного использования, отличная от цикла for, или мне, возможно, придется расшириться, чтобы вернуть и установить оба необходимых значения? в любом случае большое спасибо или ваш вклад и усилия. - person peet; 22.03.2013
comment
@peet - Извини, приятель, но я не уверен, о чем ты спрашиваешь. Вы спрашиваете, требуется ли вам использовать внешний пакетный скрипт для получения нужных вам значений? Нет, это не требуется. Что касается остальной части вашего вопроса, я думаю, мне нужен кто-то, кто переведет two vars of findable 10 ones i was thinkin about to double it на английский для меня. :› - person rojo; 22.03.2013
comment
извините, я имел в виду, что мне нужна функция, подобная for (call fetch.bat), чтобы поймать возврат fetch.bat без окончания setlocal, что позволило бы значениям сохраняться до тех пор, пока другой скрипт не запустится и, возможно, случайно не использует его. во второй части я имел в виду, что fetch.bat (ваш http-скрипт) будет анализировать около 10 параметров, из которых мне нужно только 2. и чтобы не усложнять, я думал о том, чтобы удвоить ваш http-скрипт в двух bat (по одному для каждого var), что может быть проще для меня, чем находить два параметра за один запуск fetch.bat и возвращать 2 необходимых (из 10 найденных) значений. - person peet; 23.03.2013
comment
вау, я написал предпоследний комментарий к вашему первому ответу, в то время как вы тем временем уже адаптировали и изменили код - через минуту я получу свой лучший скрипт - person peet; 23.03.2013
comment
@peet - Вы спрашиваете, как получить самое низкое и самое высокое значение из полученных значений? Если это то, о чем вы спрашиваете, я добавил пример, показывающий, как это сделать. - person rojo; 23.03.2013
comment
нет, два моих искомых значения зависят только от их именования сверху и снизу, я добавил скелет скрипта, это может быть полезно для других, возможно, тоже - person peet; 23.03.2013
comment
должен упомянуть очень умный способ установить два значения на самые высокие и самые низкие значения, спасибо за эту идею - person peet; 23.03.2013

Ваш внутренний пакетный файл заканчивается установкой переменной среды с именем top: set top=%val1%. Вам нужно изменить это на set val1=%val1%.

...
echo !val1!
ENDLOCAL & SET val1=%val1%
person Nate Hekman    schedule 22.03.2013
comment
Не нужно ли вместо этого сделать ENDLOCAL & SET val1=!val1!? - person BDM; 22.03.2013