Weisen Sie einer Variablen mithilfe einer MS-Batchdatei die Ausgabe eines Programms zu

290

Ich muss die Ausgabe eines Programms einer Variablen mithilfe einer MS-Batchdatei zuweisen.

Also in GNU Bash Shell würde ich verwenden VAR=$(application arg0 arg1). Ich benötige ein ähnliches Verhalten in Windows unter Verwendung einer Batchdatei.

So etwas wie set VAR=application arg0 arg1.

initialZero
quelle

Antworten:

433

Ein Weg ist:

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

Ein anderer ist:

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

Beachten Sie, dass das erste %In %%iverwendet wird, um das %Nachher zu maskieren, und benötigt wird, wenn der obige Code in einer Batchdatei und nicht in der Befehlszeile verwendet wird. Stellen Sie test.batsich vor, Sie haben so etwas wie:

for /f %%i in ('c:\cygwin64\bin\date.exe +"%%Y%%m%%d%%H%%M%%S"') do set datetime=%%i
echo %datetime%
Carlos Gutiérrez
quelle
11
Dies ist ein großartiger Trick, ich frage mich, warum es mit einer Pfeife nicht funktioniert
Bill K
25
Dies funktioniert nur für die Ausgabe, bei der es sich um eine einzelne Textzeile handelt (nachfolgende Zeilen werden nach dem ersten Zeilenumbruch weggelassen).
GroovyCakes
20
@Machta Die Pfeife muss mit einem ^ -Zeichen davor im Ausdruck in Parens versehen werden. Beispiel:for /f "tokens=3" %%i in ('route print ^| findstr "\<0.0.0.0\>"') do set "myVar=%%i"
Emanuele Del Grande
8
Arbeiten Sie nicht für Zeilen mit Leerzeichen. Beispiel: Setzen Sie für / f %% i in ('ver') VAR = %% i. Wie @Renat schrieb, sollte "tokens = *"
hinzugefügt werden
2
@GroovyCakes Ihre Frage über mehrere Zeilen in der Ausgabe wird durch diese Antwort auf eine doppelte Frage beantwortet
icc97
67

Als Ergänzung zu dieser vorherigen Antwort können Pipes in einer for-Anweisung verwendet werden, die durch ein Caret-Symbol gekennzeichnet ist:

    for /f "tokens=*" %%i in ('tasklist ^| grep "explorer"') do set VAR=%%i
Renat
quelle
1
Zwei wichtige Punkte: Verwenden Sie Token zum Erfassen und Caret, um aus dem Rohr zu entkommen.
Christopher Oezbek
6
Entsprechende Version, die auf der CLI funktioniert und zum einfacheren Basteln kopiert werden kann: for /f "tokens=*" %i in ('tasklist ^| findstr explorer') do @echo %iIm Allgemeinen usebackqsollte die Version jedoch zur Verarbeitung komplexer Befehle verwendet werden.
Amit Naidu
Tokens wurden benötigt, um Leerzeichen in der Ausgabe zu verarbeiten.
Mark Ingram
Zitate funktionieren auch für mich so : for /f "tokens=*" %%i in ('"tasklist | grep explorer"') do set VAR=%%i. Einfacher für mich, wenn der Befehl selbst keine Anführungszeichen enthält.
Paul
10

@OP können Sie for-Schleifen verwenden , um den Rückgabestatus Ihres Programms zu erfassen, wenn es etwas anderes als Zahlen ausgibt

Ghostdog74
quelle
8

Angenommen, die Ausgabe Ihrer Anwendung ist ein numerischer Rückkehrcode, können Sie Folgendes tun

application arg0 arg1
set VAR=%errorlevel%
akf
quelle
5
Leider ist die Ausgabe eine Zeichenfolge.
initialZero
OK. Ich werde dies für die Nachwelt behalten, aber werfen Sie einen Blick auf den Link von @ jdigital, der über das Weiterleiten von Ausgaben an eine temporäre Datei spricht.
Akf
1
Die Ausgabe des Programms an stdout und stderr unterscheidet sich von seinem ganzzahligen Rückgabewert. Ein Programm kann sowohl einen ganzzahligen Wert wie im obigen Beispiel zurückgeben als auch eine Zeichenfolge an die Konsole senden (oder in eine Datei oder an eine andere Stelle umleiten). Sie schließen sich nicht gegenseitig aus und sind zwei verschiedene Konzepte.
David Rector
7

Beim Ausführen: for /f %%i in ('application arg0 arg1') do set VAR=%%iIch habe eine Fehlermeldung erhalten: %% Ich war zu diesem Zeitpunkt unerwartet. Als Fix musste ich oben als ausführenfor /f %i in ('application arg0 arg1') do set VAR=%i

Munish Mehta
quelle
9
In einer Batch-Datei, die Sie benötigen, %%und außerhalb einer Batch-Datei in einer Befehlszeile, die Sie benötigen%
Jerry Jeremiah
2

Zusätzlich zur Antwort können Sie keine Umleitungsoperatoren für die Ausgabe im festgelegten Teil der forSchleife verwenden (z. B. wenn Sie die Stderror-Ausgabe eines Benutzers ausblenden und eine schönere Fehlermeldung anzeigen möchten). Stattdessen musst du ihnen mit einem Caret-Zeichen entkommen ( ^):

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

Referenz: Leiten Sie die Ausgabe des Befehls in die for-Schleife des Batch-Skripts um

Kubo2
quelle
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
quelle
(plus1) für Backticks Erklärung
Sandburg
1

Sie können ein Batch-Makro zum einfachen Erfassen von Befehlsausgaben verwenden, ähnlich wie das Verhalten der Bash-Shell.

Die Verwendung des Makros ist einfach und sieht so aus

%$set% VAR=application arg1 arg2

Und es funktioniert auch mit Rohren

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

Das Makro verwendet die Variable wie ein Array und speichert jede Zeile in einem separaten Index.
Im Beispiel %$set% allDrives="wmic logicaldiskwerden die folgenden Variablen erstellt:

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>

Um es zu verwenden, ist es nicht wichtig zu verstehen, wie das Makro selbst funktioniert.

Das vollständige Beispiel

@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
quelle
0

Ich habe das Skript geschrieben, das alle 5 Sekunden an google.com pingt und die Ergebnisse mit der aktuellen Zeit protokolliert. Hier finden Sie die Ausgabe an Variablen "commandLineStr" (mit Indizes)

@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
quelle