Przypisz dane wyjściowe programu do zmiennej przy użyciu pliku wsadowego MS

290

Muszę przypisać wyjście programu do zmiennej przy użyciu pliku wsadowego MS.

Więc w powłoce GNU Bash użyłbym VAR=$(application arg0 arg1). Potrzebuję podobnego zachowania w systemie Windows przy użyciu pliku wsadowego.

Coś jak set VAR=application arg0 arg1.

initialZero
źródło

Odpowiedzi:

433

Jednym ze sposobów jest:

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

Innym jest:

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

Zauważ, że pierwszy %w %%isłuży do ucieczki %po nim i jest potrzebne do korzystania powyższy kod w pliku wsadowym zamiast w wierszu poleceń. Wyobraź sobie, że masz test.batcoś takiego:

for /f %%i in ('c:\cygwin64\bin\date.exe +"%%Y%%m%%d%%H%%M%%S"') do set datetime=%%i
echo %datetime%
Carlos Gutiérrez
źródło
11
To świetna sztuczka, zastanawiam się, dlaczego to nie działa z fajką
Bill K
25
Działa to tylko w przypadku danych wyjściowych, które są pojedynczymi wierszami tekstu (kolejne wiersze są pomijane po pierwszej linii podziału).
GroovyCakes,
20
@Machta rura musi być poprzedzona znakiem ^, wewnątrz wyrażenia w parens. Przykład:for /f "tokens=3" %%i in ('route print ^| findstr "\<0.0.0.0\>"') do set "myVar=%%i"
Emanuele Del Grande
8
Nie pracuj dla linii ze spacjami. Na przykład: dla / f %% i in ('ver') ustaw VAR = %% i. Jak napisano @Renat, należy dodać „tokens = *”
Yura
2
@GroovyCakes Na twoje pytanie dotyczące wielu wierszy w odpowiedzi odpowiada ta odpowiedź na zduplikowane pytanie
icc97
67

Jako uzupełnienie do poprzedniej odpowiedzi , potoki mogą być używane wewnątrz instrukcji for, poprzedzone znakiem karetki:

    for /f "tokens=*" %%i in ('tasklist ^| grep "explorer"') do set VAR=%%i
Renat
źródło
1
Dwa ważne punkty: Użyj żetonów, aby schwytać, i karetki, aby uciec z rury.
Christopher Oezbek
6
Równoważna wersja, która działa na interfejsie CLI i można ją skopiować i wkleić w celu łatwiejszego majsterkowania: for /f "tokens=*" %i in ('tasklist ^| findstr explorer') do @echo %iOgólnie jednak usebackqnależy jej używać do obsługi złożonych poleceń.
Amit Naidu
Tokeny były potrzebne do obsługi spacji na wyjściu.
Mark Ingram
Cytaty pracować także dla mnie, tak: for /f "tokens=*" %%i in ('"tasklist | grep explorer"') do set VAR=%%i. Łatwiej dla mnie, jeśli w samym poleceniu nie ma cudzysłowów.
Paul
10

@OP, możesz użyć pętli do przechwycenia statusu zwracanego przez twój program, jeśli wyświetla on coś innego niż liczby

ghostdog74
źródło
8

zakładając, że dane wyjściowe aplikacji są numerycznym kodem powrotu, możesz wykonać następujące czynności

application arg0 arg1
set VAR=%errorlevel%
akf
źródło
5
Niestety, wynik jest ciągiem.
initialZero
ok. zachowam to dla potomności, ale spójrz na link @ jdigital, który mówi o przesyłaniu danych wyjściowych do pliku tymczasowego.
akf
1
Dane wyjściowe programu na stdout i stderr różnią się od wartości zwracanej przez liczby całkowite. Program może zarówno zwrócić wartość całkowitą jak w powyższym przykładzie, jednocześnie wysyłając ciąg do konsoli (lub przekierowany do pliku lub w innym miejscu). Nie wykluczają się wzajemnie i są to dwa różne pojęcia.
David Rector,
7

Podczas wykonywania: for /f %%i in ('application arg0 arg1') do set VAR=%%iotrzymywałem błąd: %% byłem w tej chwili nieoczekiwany. Jako poprawkę musiałem wykonać powyżej jakofor /f %i in ('application arg0 arg1') do set VAR=%i

Munish Mehta
źródło
9
W pliku wsadowym potrzebujesz %%i poza plikiem wsadowym w wierszu polecenia, którego potrzebujesz%
Jerry Jeremiah
2

Oprócz odpowiedzi nie można bezpośrednio używać operatorów przekierowywania danych wyjściowych w ustalonej części forpętli (np. Jeśli chcesz ukryć dane wyjściowe stderror przed użytkownikiem i podać ładniejszy komunikat o błędzie). Zamiast tego musisz uciec przed nimi za pomocą znaku karetki ( ^):

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

Odwołanie: Przekieruj wyjście polecenia w pętli skryptu wsadowego

Kubo2
źródło
1
@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
rcm
źródło
(plus1)
Sandburg,
1

Możesz użyć makra wsadowego do prostego przechwytywania danych wyjściowych poleceń, trochę jak zachowanie powłoki bash.

Użycie makra jest proste i wygląda jak

%$set% VAR=application arg1 arg2

I działa nawet z rurami

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

Makro używa zmiennej jak tablicy i przechowuje każdą linię w osobnym indeksie.
W próbce %$set% allDrives="wmic logicaldiskzostaną utworzone następujące zmienne:

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:
allDrives=<contains the complete text with line feeds>

Aby go użyć, nie jest ważne, aby zrozumieć, jak działa samo makro.

Pełny przykład

@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 (0 1 !%~1.max!) 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 LF=^
%=empty=%
)
(set \n=^^^
%=empty=%
)

set $set=FOR /L %%N in (1 1 2) dO IF %%N==2 ( %\n%
    setlocal EnableDelayedExpansion                                 %\n%
    for /f "tokens=1,* delims== " %%1 in ("!argv!") do (            %\n%
        endlocal                                                    %\n%
        endlocal                                                    %\n%
        set "%%~1.Len=0"                                            %\n%
        set "%%~1="                                                 %\n%
        if "!!"=="" (                                               %\n%
            %= Used if delayed expansion is enabled =%              %\n%
                setlocal DisableDelayedExpansion                    %\n%
                for /F "delims=" %%O in ('"%%~2 | findstr /N ^^"') do ( %\n%
                if "!!" NEQ "" (                                    %\n%
                    endlocal                                        %\n%
                    )                                               %\n%
                setlocal DisableDelayedExpansion                    %\n%
                set "line=%%O"                                      %\n%
                setlocal EnableDelayedExpansion                     %\n%
                set pathExt=:                                       %\n%
                set path=;                                          %\n%
                set "line=!line:^=^^!"                              %\n%
                set "line=!line:"=q"^""!"                           %\n%
                call set "line=%%line:^!=q""^!%%"                   %\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%
                        if %%C == 0 (                               %\n%
                            set "%%~1=%%~L" !                       %\n%
                        ) ELSE (                                    %\n%
                            set "%%~1=!%%~1!!LF!%%~L" !             %\n%
                        )                                           %\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 DisableDelayedExpansion^&set argv=

goto :eof
jeb
źródło
0

Napisałem skrypt, który pinguje google.com co 5 sekund i rejestruje wyniki na bieżąco. Tutaj możesz znaleźć dane wyjściowe do zmiennych „commandLineStr” (z indeksami)

@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
Ja Vy
źródło