Tetapkan output suatu program ke variabel menggunakan file batch MS

290

Saya perlu menetapkan output suatu program ke variabel menggunakan file batch MS.

Jadi di GNU Bash shell saya akan gunakan VAR=$(application arg0 arg1). Saya perlu perilaku serupa di Windows menggunakan file batch.

Sesuatu seperti set VAR=application arg0 arg1.

initialZero
sumber

Jawaban:

433

Salah satu caranya adalah:

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

Lainnya adalah:

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

Perhatikan bahwa %in pertama %%idigunakan untuk melarikan diri %setelah itu dan diperlukan saat menggunakan kode di atas dalam file batch daripada pada baris perintah. Bayangkan, Anda test.batmemiliki sesuatu seperti:

for /f %%i in ('c:\cygwin64\bin\date.exe +"%%Y%%m%%d%%H%%M%%S"') do set datetime=%%i
echo %datetime%
Carlos Gutiérrez
sumber
11
Ini adalah trik yang hebat, saya bertanya-tanya mengapa itu tidak bekerja dengan pipa
Bill K
25
Ini hanya berfungsi untuk output yang merupakan satu baris teks (baris berikutnya dihilangkan setelah jeda baris pertama).
GroovyCakes
20
@Machta pipa harus diloloskan dengan tanda ^ sebelum itu, di dalam ekspresi di parens. Contoh:for /f "tokens=3" %%i in ('route print ^| findstr "\<0.0.0.0\>"') do set "myVar=%%i"
Emanuele Del Grande
8
Jangan bekerja untuk garis dengan spasi. Sebagai contoh: untuk / f %% i in ('ver') lakukan set VAR = %% i. Seperti yang ditulis @Renat, harus menambahkan "token = *"
Yura Shinkarev
2
@GroovyCakes Pertanyaan Anda tentang beberapa baris dalam output dijawab oleh jawaban ini pada pertanyaan rangkap
icc97
67

Sebagai tambahan untuk jawaban sebelumnya , pipa dapat digunakan di dalam pernyataan for, diloloskan dengan simbol tanda sisipan:

    for /f "tokens=*" %%i in ('tasklist ^| grep "explorer"') do set VAR=%%i
Renat
sumber
1
Dua poin penting: Gunakan token untuk menangkap dan memberi tanda agar lolos dari pipa.
Christopher Oezbek
6
Versi yang setara yang bekerja pada CLI dan dapat disalin-tempel untuk bermain-main lebih mudah: for /f "tokens=*" %i in ('tasklist ^| findstr explorer') do @echo %iTetapi secara umum, usebackqharus digunakan untuk menangani perintah yang kompleks.
Amit Naidu
Token diperlukan untuk menangani spasi di output.
Mark Ingram
Kutipan bekerja dengan baik bagi saya, seperti ini: for /f "tokens=*" %%i in ('"tasklist | grep explorer"') do set VAR=%%i. Lebih mudah bagi saya jika tidak ada tanda kutip di perintah itu sendiri.
Paul
10

@OP, Anda dapat menggunakan loop untuk menangkap status pengembalian program Anda, jika menghasilkan sesuatu selain angka

ghostdog74
sumber
8

dengan asumsi bahwa output aplikasi Anda adalah kode pengembalian numerik, Anda dapat melakukan hal berikut

application arg0 arg1
set VAR=%errorlevel%
akf
sumber
5
Sayangnya, outputnya berupa string.
initialZero
baik. saya akan menyimpan ini untuk anak cucu, tetapi lihatlah tautan @ jdigital, yang berbicara tentang keluaran perpipaan ke file temp.
akf
1
Output program ke stdout dan stderr berbeda dari nilai pengembalian integernya. Suatu program dapat mengembalikan nilai integer seperti dalam contoh di atas, sementara juga mengirim string ke konsol (atau dialihkan ke file atau di tempat lain). Mereka tidak saling eksklusif dan dua konsep yang berbeda.
David Rektor
7

Sedang Dieksekusi: for /f %%i in ('application arg0 arg1') do set VAR=%%isaya mendapatkan kesalahan: %% saya tidak terduga saat ini. Sebagai perbaikan, saya harus menjalankan di atas sebagaifor /f %i in ('application arg0 arg1') do set VAR=%i

Munish Mehta
sumber
9
Dalam file batch yang Anda butuhkan %%dan di luar file batch pada baris perintah yang Anda butuhkan%
Jerry Jeremiah
2

Selain jawabannya, Anda tidak bisa langsung menggunakan operator redirection output dalam set bagian dari forlingkaran (misalnya jika Anda ingin menyembunyikan keluaran stderror dari pengguna dan memberikan pesan kesalahan yang lebih baik). Sebaliknya, Anda harus melarikan diri dari mereka dengan karakter tanda sisipan (^ ):

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

Referensi: Redirect output dari perintah untuk loop script batch

Kubo2
sumber
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
sumber
(plus1) untuk penjelasan backticks
Sandburg
1

Anda bisa menggunakan kumpulan makro untuk menangkap sederhana output perintah, sedikit seperti perilaku bash shell.

Penggunaan makro sederhana dan terlihat seperti

%$set% VAR=application arg1 arg2

Dan itu bekerja bahkan dengan pipa

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

Makro menggunakan variabel seperti array dan menyimpan setiap baris dalam indeks terpisah.
Dalam sampel %$set% allDrives="wmic logicaldiskakan ada variabel-variabel berikut dibuat:

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>

Untuk menggunakannya, tidak penting untuk memahami cara kerja makro itu sendiri.

Contoh lengkap

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

Saya menulis skrip yang ping google.com setiap 5 detik dan mencatat hasil dengan waktu saat ini. Di sini Anda dapat menemukan output ke variabel "commandLineStr" (dengan indeks)

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