it-swarm.com.ru

Присвоить вывод программы переменной с помощью командного файла MS

Мне нужно назначить вывод программы для переменной с помощью командного файла MS.

Так что в GNU Bash Shell я бы использовал VAR=$(application arg0 arg1). Мне нужно подобное поведение в Windows, используя командный файл.

Что-то вроде set VAR=application arg0 arg1.

230
initialZero

Одним из способов является:

application arg0 arg1 > temp.txt
set /p VAR=<temp.txt

Другой это:

for /f %%i in ('application arg0 arg1') do set VAR=%%i

Обратите внимание, что первый % в %%i используется для экранирования % после него и необходим при использовании вышеуказанного кода в пакетном файле, а не в командной строке. Представьте, что ваш test.bat имеет что-то вроде:

for /f %%i in ('c:\cygwin64\bin\date.exe +"%%Y%%m%%d%%H%%M%%S"') do set datetime=%%i
echo %datetime%
353
Carlos Gutiérrez

В дополнение к этому предыдущему ответу , внутри оператора for могут использоваться каналы, экранированные символом каретки:

    for /f "tokens=*" %%i in ('tasklist ^| grep "Explorer"') do set VAR=%%i
57
Renat

@OP, вы можете использовать для циклов чтобы получить статус возврата вашей программы, если она выводит что-то отличное от чисел

8
ghostdog74

предполагая, что вывод вашего приложения представляет собой числовой код возврата, вы можете сделать следующее

application arg0 arg1
set VAR=%errorlevel%
6
akf

Выполняется: for /f %%i in ('application arg0 arg1') do set VAR=%%i я получаю ошибку: %% я был неожиданным в это время. Как исправить, я должен был выполнить выше как for /f %i in ('application arg0 arg1') do set VAR=%i

5
Munish Mehta

В дополнение к ответу вы не можете напрямую использовать операторы перенаправления вывода в части set цикла for (например, если вы хотите скрыть вывод stderror от пользователя и предоставить более приятное сообщение об ошибке). Вместо этого вы должны избегать их с помощью символа вставки (^):

for /f %%O in ('some-erroring-command 2^> nul') do (echo %%O)

Справка: Перенаправить вывод команды в цикл for batch script

1
Kubo2
@echo off
SETLOCAL ENABLEDELAYEDEXPANSION

REM Prefer backtick usage for command output reading:
REM ENABLEDELAYEDEXPANSION is required for actualized
REM  outer variables within for's scope;
REM within for's scope, access to modified 
REM outer variable is done via !...! syntax.

SET CHP=C:\Windows\System32\chcp.com

FOR /F "usebackq tokens=1,2,3" %%i IN (`%CHP%`) DO (
    IF "%%i" == "Aktive" IF "%%j" == "Codepage:" (
        SET SELCP=%%k
        SET SELCP=!SELCP:~0,-1!
    )
)
echo actual codepage [%SELCP%]

ENDLOCAL
0
rcm

Вы можете использовать пакетный макрос для простого захвата выходных данных команды, немного похожий на поведение командной оболочки bash. 

Использование макроса просто и выглядит как

%$set% VAR=application arg1 arg2

И это работает даже с трубами

%$set% allDrives="wmic logicaldisk get name /value | findstr "Name""

Макрос использует переменную как массив и сохраняет каждую строку в отдельном индексе.
В примере %$set% allDrives="wmic logicaldisk будут созданы следующие переменные: 

allDrives.Len=5
allDrives.Max=4
allDrives[0]=Name=C:
allDrives[1]=Name=D:
allDrives[2]=Name=F:
allDrives[3]=Name=G:
allDrives[4]=Name=Z:

Чтобы использовать его, не важно понимать, как работает сам макрос.

Полный пример

@echo off
setlocal

call :initMacro

%$set% ipOutput="ipconfig"
call :ShowVariable ipOutput
echo First line is %ipOutput[0]%

echo( 
%$set% driveNames="wmic logicaldisk get name /value | findstr "Name""
call :ShowVariable driveNames

exit /b

:ShowVariable
setlocal EnableDelayedExpansion
for /L %%n in (1 1 !%~1.len!) do (
    echo %%n: !%~1[%%n]!
)
echo(
exit /b

:initMacro
if "!!"=="" (
    echo ERROR: Delayed Expansion must be disabled while defining macros
    (goto) 2>nul
    (goto) 2>nul
)
(set \n=^^^
%=empty=%
)

set $set=FOR /L %%N in (1 1 2) DO IF %%N==2 ( %\n%
    for /f "tokens=1,* delims== " %%1 in ("!argv!") do (            %\n%
        endlocal                                                    %\n%
        endlocal                                                    %\n%
        set "%%~1.Len=0"                                            %\n%
        if "!!"=="" (                                               %\n%
            %= Used if delayed expansion is enabled =%              %\n%
            for /F "delims=" %%O in ('"%%~2 | findstr /N ^^"') do ( %\n%
                setlocal DisableDelayedExpansion                    %\n%
                set pathExt=:                                       %\n%
                set "line=%%O"                                      %\n%
                call set ^"line=%%line:"="Q"%%"                     %\n%
                call set "line=%%line:!="B"!%%"                     %\n%
                setlocal EnableDelayedExpansion                     %\n%
                set "line=!line:^=^^!"                              %\n%
                set "line=!line:"B"=^!"                             %\n%
                set "line=!line:"Q"=^"!^"                           %\n%
                set "line="!line:*:=!""                             %\n%
                for /F %%C in ("!%%~1.Len!") DO (                   %\n%
                    FOR /F "delims=" %%L in ("!line!") DO (         %\n%
                        endlocal                                    %\n%
                        endlocal                                    %\n%
                        set "%%~1[%%C]=%%~L" !                      %\n%
                    )                                               %\n%
                    set /a %%~1.Len+=1                              %\n%
                )                                                   %\n%
            )                                                       %\n%
        ) ELSE (                                                    %\n%
            %= Used if delayed expansion is disabled =%             %\n%
            for /F "delims=" %%O in ('"%%~2 | findstr /N ^^"') do ( %\n%
                setlocal DisableDelayedExpansion                    %\n%
                set "line=%%O"                                      %\n%
                setlocal EnableDelayedExpansion                     %\n%
                set "line="!line:*:=!""                             %\n%
                for /F %%C in ("!%%~1.Len!") DO (                   %\n%
                    FOR /F "delims=" %%L in ("!line!") DO (         %\n%
                        endlocal                                    %\n%
                        endlocal                                    %\n%
                        set "%%~1[%%C]=%%~L"                        %\n%
                    )                                               %\n%
                    set /a %%~1.Len+=1                              %\n%
                )                                                   %\n%
            )                                                       %\n%
        )                                                           %\n%
        set /a %%~1.Max=%%~1.Len-1                                  %\n%
        )                                                           %\n%
    ) else setlocal EnableDelayedExpansion^&setlocal^&set argv=

goto :eof
0
jeb

Я написал скрипт, который пингует google.com каждые 5 секунд и регистрирует результаты с текущим временем. Здесь вы можете найти выходные данные для переменных "commandLineStr" (с индексами)

@echo off

:LOOPSTART

echo %DATE:~0% %TIME:~0,8% >> Pingtest.log

SETLOCAL ENABLEDELAYEDEXPANSION
SET scriptCount=1
FOR /F "tokens=* USEBACKQ" %%F IN (`ping google.com -n 1`) DO (
  SET commandLineStr!scriptCount!=%%F
  SET /a scriptCount=!scriptCount!+1
)
@ECHO %commandLineStr1% >> PingTest.log
@ECHO %commandLineStr2% >> PingTest.log
ENDLOCAL

timeout 5 > nul

GOTO LOOPSTART
0
Ja Vy