Assegnare l'output di un programma a una variabile utilizzando un file batch MS


290

Devo assegnare l'output di un programma a una variabile usando un file batch MS.

Quindi nella shell GNU Bash userei VAR=$(application arg0 arg1). Ho bisogno di un comportamento simile in Windows usando un file batch.

Qualcosa del genere set VAR=application arg0 arg1.

Risposte:


433

Un modo è:

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

Un altro è:

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

Si noti che il primo %in %%iviene utilizzato per evitare il %dopo ed è necessario quando si utilizza il codice sopra in un file batch anziché sulla riga di comando. Immagina, il tuo test.batha qualcosa come:

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

11
Questo è un grande trucco, mi chiedo perché non funzioni con una pipa
Bill K

25
Funziona solo per l'output che è una singola riga di testo (righe successive omesse dopo la prima interruzione di riga).
GroovyCakes

20
@Machta la pipe deve essere sfuggita con un segno ^ prima di esso, all'interno dell'espressione tra parentesi. Esempio:for /f "tokens=3" %%i in ('route print ^| findstr "\<0.0.0.0\>"') do set "myVar=%%i"
Emanuele Del Grande,

8
Non lavorare per la linea con gli spazi. Ad esempio: per / f %% i in ('ver') impostare VAR = %% i. Come scritto @Renat, dovrebbe aggiungere "token = *"
Yura Shinkarev

2
@GroovyCakes La tua domanda su più righe nell'output sono risposto da questa risposta su una questione duplicato
icc97

67

In aggiunta a questa risposta precedente , le pipe possono essere utilizzate all'interno di un'istruzione for, sfuggita al simbolo di un cursore:

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

1
Due punti importanti: utilizzare i token per catturare e curare per sfuggire alla pipa.
Christopher Oezbek,

6
Versione equivalente che funziona sull'interfaccia della riga di comando e che può essere incollata per semplificare gli armeggi: for /f "tokens=*" %i in ('tasklist ^| findstr explorer') do @echo %ima in generale, usebackqdovrebbe essere utilizzata per gestire comandi complessi.
Amit Naidu,

I token erano necessari per gestire gli spazi nell'output.
Mark Ingram,

Citazioni lavoro come bene per me, in questo modo: for /f "tokens=*" %%i in ('"tasklist | grep explorer"') do set VAR=%%i. Più facile per me se non ci sono virgolette nel comando stesso.
Paul,

10

@OP, è possibile utilizzare per i loop per acquisire lo stato di ritorno del programma, se genera qualcosa di diverso dai numeri


8

supponendo che l'output dell'applicazione sia un codice di ritorno numerico, è possibile effettuare le seguenti operazioni

application arg0 arg1
set VAR=%errorlevel%

5
Sfortunatamente, l'output è una stringa.
Zero

ok. lo terrò per i posteri, ma dai un'occhiata al link di @ jdigital, che parla dell'output del piping in un file temporaneo.
Akf

1
L'output del programma su stdout e stderr è diverso dal suo valore di ritorno intero. Un programma può sia restituire un valore intero come nell'esempio precedente, sia inviare una stringa alla console (o reindirizzato a un file o altrove). Non si escludono a vicenda e sono due concetti diversi.
David Rector,

7

In esecuzione: for /f %%i in ('application arg0 arg1') do set VAR=%%istavo ricevendo un errore: %% ero imprevisto in questo momento. Come soluzione, ho dovuto eseguire sopra comefor /f %i in ('application arg0 arg1') do set VAR=%i


9
In un file batch è necessario %%e all'esterno di un file batch su una riga di comando è necessario%
Jerry Jeremiah,

2

Oltre alla risposta, non è possibile utilizzare direttamente gli operatori di reindirizzamento dell'output nella parte impostata del forloop (ad es. Se si desidera nascondere l'output stderror da un utente e fornire un messaggio di errore migliore). Invece, devi scappare da loro con un carattere cursore ( ^):

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

Riferimento: reindirizzare l'output del comando per il ciclo di script batch


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

(più 1) per la spiegazione dei backticks
Sandburg,

1

È possibile utilizzare una macro batch per la semplice acquisizione degli output dei comandi, un po 'come il comportamento della shell bash.

L'uso della macro è semplice e sembra

%$set% VAR=application arg1 arg2

E funziona anche con i tubi

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

La macro utilizza la variabile come un array e memorizza ogni riga in un indice separato.
Nell'esempio %$set% allDrives="wmic logicaldiskverranno create le seguenti variabili:

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>

Per usarlo, non è importante capire come funziona la macro stessa.

L'esempio completo

@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

0

Ho scritto lo script che esegue il ping di google.com ogni 5 secondi e registrando i risultati con l'ora corrente. Qui puoi trovare l'output delle variabili "commandLineStr" (con indici)

@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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.