MSバッチファイルを使用してプログラムの出力を変数に割り当てる


290

MSバッチファイルを使用して、プログラムの出力を変数に割り当てる必要があります。

したがって、GNU Bashシェルではを使用しますVAR=$(application arg0 arg1)。Windowsでバッチファイルを使用して同様の動作が必要です。

のようなものset VAR=application arg0 arg1

回答:


433

1つの方法は次のとおりです。

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

もう一つは:

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

最初の%in %%i%後のエスケープに使用され、コマンドラインではなくバッチファイルで上記のコードを使用する場合に必要です。想像してください、あなたのtest.batようなものがあります:

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

11
これは素晴らしいトリックです、なぜそれがパイプで機能しないのでしょうか
Bill K

25
これは、1行のテキスト(後続の行が最初の改行の後に省略される)である出力に対してのみ機能します。
GroovyCakes 2015

20
@Machtaパイプは、括弧内の式の内部で、その前に^記号を付けてエスケープする必要があります。例:for /f "tokens=3" %%i in ('route print ^| findstr "\<0.0.0.0\>"') do set "myVar=%%i"
Emanuele Del Grande

8
スペースのある行には機能しません。例:/ f %% i in( 'ver')の場合、VAR = %% iを設定します。@Renatに書いたように、「tokens = *」を追加する必要があります
Yura

2
@GroovyCakes出力内の複数の行に関するあなたの質問は、重複した質問に対するこの回答で答えられます
icc97

67

この前の回答に加えて、パイプをforステートメント内で使用して、キャレット記号でエスケープすることができます。

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

1
2つの重要なポイント:トークンを使用してキャプチャし、キャレットを使用してパイプから脱出します。
クリストファーOezbek 2014年

6
CLIで機能する同等のバージョンで、いじくりを簡単にするためにコピーして貼り付けることができます。for /f "tokens=*" %i in ('tasklist ^| findstr explorer') do @echo %iただし、一般的には、usebackq複雑なコマンドを処理するために使用する必要があります。
アミットナイドゥ2017

トークンは、出力のスペースを処理するために必要でした。
Mark Ingram、

次のように、引用は私にとってもうまくいきますfor /f "tokens=*" %%i in ('"tasklist | grep explorer"') do set VAR=%%i。コマンド自体に引用符がない場合、私にとってはより簡単です。
ポール

10

@ OP、forループを使用して、プログラムが数値以外のものを出力する場合は、プログラムの戻りステータスをキャプチャできます。


8

アプリケーションの出力が数値の戻りコードであると仮定すると、次のことができます

application arg0 arg1
set VAR=%errorlevel%

5
残念ながら、出力は文字列です。
initialZero 2010

OK。後世のためにこれを保持しますが、一時ファイルへの出力のパイプ処理について説明している@jdigitalのリンクを見てください。
akf 2010

1
stdoutおよびstderrへのプログラムの出力は、整数の戻り値とは異なります。プログラムは、上記の例のように整数値を返すと同時に、コンソールに文字列を送信する(またはファイルなどにリダイレクトする)ことができます。これらは相互に排他的ではなく、2つの異なる概念です。
David Rector

7

実行中:for /f %%i in ('application arg0 arg1') do set VAR=%%iエラーが発生しました:%% iは現時点では予期されていませんでした。修正として、上記のように実行する必要がありましたfor /f %i in ('application arg0 arg1') do set VAR=%i


9
必要なバッチファイル内と必要な%%コマンドライン上のバッチファイル外%
Jerry Jeremiah

2

答えに加えて、ループの設定部分で出力リダイレクト演算子を直接使用することはできませんfor(たとえば、ユーザーからstderror出力を非表示にして、より適切なエラーメッセージを提供する場合)。代わりに、キャレット文字(^)でエスケープする必要があります。

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

参照:バッチスクリプトのforループでコマンドの出力をリダイレクトする


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

(plus1)バッククォートの説明
Sandburg、

1

バッチマクロを使用して、コマンド出力を簡単にキャプチャできます。これは、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:
allDrives=<contains the complete text with line feeds>

それを使用するために、マクロ自体がどのように機能するかを理解することは重要ではありません。

完全な例

@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

5秒ごとにgoogle.comにpingし、現在の時間で結果をログに記録するスクリプトを作成しました。ここでは、変数「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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.