กำหนดเอาต์พุตของโปรแกรมให้กับตัวแปรโดยใช้ไฟล์แบตช์ MS


290

ฉันต้องกำหนดผลลัพธ์ของโปรแกรมให้กับตัวแปรโดยใช้ไฟล์แบตช์ MS

ดังนั้นใน GNU VAR=$(application arg0 arg1)เปลือกทุบตีผมจะใช้ ฉันต้องการพฤติกรรมที่คล้ายกันใน Windows โดยใช้ไฟล์แบตช์

set VAR=application arg0 arg1สิ่งที่ชอบ

คำตอบ:


433

วิธีหนึ่งคือ:

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

อีกอย่างคือ:

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

โปรดทราบว่าการใช้ครั้งแรก%ใน%%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
ใช้งานได้กับเอาต์พุตซึ่งเป็นข้อความบรรทัดเดียวเท่านั้น (บรรทัดถัดมาที่ตัดออกหลังจากตัวแบ่งบรรทัดแรก)
GroovyCakes

20
@Machta ไปป์ต้องหนีด้วยเครื่องหมาย ^ ก่อนหน้านี้ภายในนิพจน์ใน parens ตัวอย่าง:for /f "tokens=3" %%i in ('route print ^| findstr "\<0.0.0.0\>"') do set "myVar=%%i"
Emanuele Del Grande

8
อย่าทำงานให้สอดคล้องกับช่องว่าง ตัวอย่างเช่น: สำหรับ / f %% i ใน ('ver') ให้ตั้ง VAR = %% i ตามที่เขียน @Renat ควรเพิ่ม "tokens = *"
Yura Shinkarev

2
@GroovyCakes คำถามของคุณเกี่ยวกับหลายบรรทัดในผลลัพธ์จะได้รับคำตอบจากคำตอบนี้สำหรับคำถามที่ซ้ำกัน
icc97

67

นอกเหนือจากคำตอบก่อนหน้านี้ท่อสามารถใช้ภายในคำสั่ง for โดยใช้เครื่องหมายคาเร็ต:

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

1
สองจุดสำคัญ: ใช้โทเค็นในการจับและคาเร็ตเพื่อหลบหนีท่อ
Christopher Oezbek

6
รุ่นที่เทียบเท่ากับที่ทำงานบน CLI และสามารถคัดลอกวางเพื่อให้แก้ไขได้ง่ายขึ้น: for /f "tokens=*" %i in ('tasklist ^| findstr explorer') do @echo %iแต่โดยทั่วไปusebackqควรใช้เพื่อจัดการกับคำสั่งที่ซับซ้อน
Amit Naidu

ต้องใช้โทเค็นเพื่อจัดการช่องว่างในเอาต์พุต
ทำเครื่องหมายอินแกรม

for /f "tokens=*" %%i in ('"tasklist | grep explorer"') do set VAR=%%iคำคมทำงานได้ดีสำหรับฉันเช่นนี้ ง่ายกว่าสำหรับฉันถ้าไม่มีคำพูดในตัวคำสั่ง
เปาโล


8

สมมติว่าเอาต์พุตของแอปพลิเคชันของคุณเป็นรหัสส่งคืนเป็นตัวเลขคุณสามารถทำสิ่งต่อไปนี้

application arg0 arg1
set VAR=%errorlevel%

5
น่าเสียดายที่เอาต์พุตเป็นสตริง
initialZero

ตกลง. ฉันจะเก็บสิ่งนี้ไว้สำหรับคนรุ่นหลัง แต่ลองดูที่ลิงค์ของ @ jdigital ซึ่งพูดถึงการส่งออก piping ไปยังไฟล์ temp
akf

1
เอาต์พุตของโปรแกรมไปยัง stdout และ stderr นั้นแตกต่างจากค่าส่งคืนจำนวนเต็ม โปรแกรมสามารถส่งคืนค่าจำนวนเต็มเช่นในตัวอย่างข้างต้นในขณะที่ยังส่งสตริงไปยังคอนโซล (หรือเปลี่ยนเส้นทางไปยังไฟล์หรือที่อื่น ๆ ) พวกเขาไม่ได้เป็นพิเศษร่วมกันและเป็นสองแนวคิดที่แตกต่าง
David Rector

7

กำลังดำเนินการ: for /f %%i in ('application arg0 arg1') do set VAR=%%iฉันได้รับข้อผิดพลาด: %% ฉันไม่คาดคิดในขณะนี้ เพื่อแก้ไขฉันต้องดำเนินการดังกล่าวข้างต้นfor /f %i in ('application arg0 arg1') do set VAR=%i


9
ในไฟล์แบทช์คุณต้องการ%%และอยู่นอกแบตช์ไฟล์ในบรรทัดคำสั่งที่คุณต้องการ%
Jerry Jeremiah

2

นอกจากคำตอบแล้วคุณไม่สามารถใช้โอเปอเรเตอร์การเปลี่ยนเส้นทางโดยตรงในส่วนชุดforลูป (เช่นหากคุณต้องการซ่อนเอาต์พุตสเตรเรจจากผู้ใช้และให้ข้อความแสดงข้อผิดพลาดที่ดีกว่า) คุณต้องหลบหนีด้วยอักขระคาเร็ต ( ^):

for /f %%O in ('some-erroring-command 2^> nul') do (echo %%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

(บวก 1) สำหรับคำอธิบาย backticks
Sandburg

1

คุณสามารถใช้มาโครแบบแบตช์เพื่อจับเอาท์พุทคำสั่งแบบง่าย ๆ เช่นพฤติกรรมของ bash shell

การใช้งานมาโครนั้นง่ายและดูเหมือนว่า

%$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

ฉันเขียนสคริปต์ที่ส่ง google.com ทุก 5 วินาทีและบันทึกผลลัพธ์ด้วยเวลาปัจจุบัน ที่นี่คุณสามารถค้นหาผลลัพธ์ไปยังตัวแปร "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.