Gán đầu ra của chương trình cho một biến bằng tệp bó MS


290

Tôi cần gán đầu ra của chương trình cho một biến bằng tệp bó MS.

Vì vậy, trong GNU Bash shell tôi sẽ sử dụng VAR=$(application arg0 arg1). Tôi cần một hành vi tương tự trong Windows bằng cách sử dụng một tệp bó.

Một cái gì đó như set VAR=application arg0 arg1.

Câu trả lời:


433

Một cách là:

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

Cái khác là:

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

Lưu ý rằng người đầu tiên %trong %%iđược sử dụng để thoát khỏi %sau khi nó và là cần thiết khi sử dụng các mã trên trong một tập tin thực thi chứ không phải trên dòng lệnh. Hãy tưởng tượng, bạn test.batcó một cái gì đó như:

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

11
Đây là một mẹo hay, tôi tự hỏi tại sao nó không hoạt động với một đường ống
Bill K

25
Điều này chỉ hoạt động cho đầu ra là một dòng văn bản (dòng tiếp theo bị bỏ qua sau khi ngắt dòng đầu tiên).
GroovyCakes

20
@Machta đường ống phải được thoát với dấu ^ trước nó, bên trong biểu thức trong parens. Ví dụ:for /f "tokens=3" %%i in ('route print ^| findstr "\<0.0.0.0\>"') do set "myVar=%%i"
Emanuele Del Grande

8
Không làm việc cho phù hợp với không gian. Ví dụ: for / f %% i in ('ver') do đặt VAR = %% i. Như đã viết @Renat, nên thêm "mã thông báo = *"
Yura Shinkarev

2
@GroovyCakes Câu hỏi của bạn về nhiều dòng trong đầu ra được trả lời bằng câu trả lời này cho một câu hỏi trùng lặp
icc97

67

Ngoài ra, trong câu trả lời trước đó , các đường ống có thể được sử dụng trong câu lệnh for, được thoát bằng biểu tượng dấu mũ:

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

1
Hai điểm quan trọng: Sử dụng mã thông báo để chụp và dấu mũ để thoát khỏi đường ống.
Christopher Oezbek

6
Phiên bản tương đương hoạt động trên CLI và có thể được sao chép để dán dễ dàng hơn: for /f "tokens=*" %i in ('tasklist ^| findstr explorer') do @echo %iNhưng nói chung, usebackqnên được sử dụng để xử lý các lệnh phức tạp.
Amit N Nikol

Mã thông báo là cần thiết để xử lý không gian trong đầu ra.
Đánh dấu Ingram

Báo giá cũng làm việc cho tôi, như thế này : for /f "tokens=*" %%i in ('"tasklist | grep explorer"') do set VAR=%%i. Dễ dàng hơn cho tôi nếu không có dấu ngoặc kép trong lệnh.
Paul

10

@OP, bạn có thể sử dụng các vòng lặp để nắm bắt trạng thái trả về của chương trình, nếu nó xuất ra thứ gì đó không phải là số


8

giả sử rằng đầu ra của ứng dụng của bạn là mã trả về số, bạn có thể làm như sau

application arg0 arg1
set VAR=%errorlevel%

5
Thật không may, đầu ra là một chuỗi.
initZero

đồng ý. tôi sẽ giữ điều này cho hậu thế, nhưng hãy xem liên kết của @ jdigital, nói về đầu ra đường ống đến một tệp tạm thời.
akf

1
Đầu ra của chương trình tới thiết bị xuất chuẩn và thiết bị xuất chuẩn khác với giá trị trả về số nguyên của nó. Một chương trình có thể trả về một giá trị số nguyên như trong ví dụ trên, đồng thời gửi một chuỗi tới bàn điều khiển (hoặc được chuyển hướng đến một tệp hoặc ở nơi khác). Chúng không loại trừ lẫn nhau và là hai khái niệm khác nhau.
Hiệu trưởng David

7

Khi thực hiện: for /f %%i in ('application arg0 arg1') do set VAR=%%itôi đã gặp lỗi: %% tôi không ngờ vào lúc này. Để khắc phục, tôi đã phải thực hiện ở trên nhưfor /f %i in ('application arg0 arg1') do set VAR=%i


9
Trong một tệp bó bạn cần %%và bên ngoài một tệp bó trên một dòng lệnh bạn cần%
Jerry Jeremiah

2

Ngoài câu trả lời, bạn không thể trực tiếp sử dụng các toán tử chuyển hướng đầu ra trong phần thiết lập của forvòng lặp (ví dụ: nếu bạn muốn ẩn đầu ra stderror khỏi người dùng và cung cấp thông báo lỗi đẹp hơn). Thay vào đó, bạn phải thoát chúng bằng ký tự dấu mũ ( ^):

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

Tham khảo: Chuyển hướng đầu ra của lệnh trong vòng lặp của tập lệnh bó


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) để giải thích về backticks
Sandburg

1

Bạn có thể sử dụng một macro bó để chụp các đầu ra lệnh đơn giản, giống như hành vi của bash shell.

Việc sử dụng macro rất đơn giản và trông giống như

%$set% VAR=application arg1 arg2

Và nó hoạt động ngay cả với đường ống

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

Macro sử dụng biến như một mảng và lưu trữ mỗi dòng trong một chỉ mục riêng biệt.
Trong mẫu của %$set% allDrives="wmic logicaldiskcác biến sau sẽ được tạo:

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>

Để sử dụng nó, không quan trọng để hiểu cách thức hoạt động của macro.

Ví dụ đầy đủ

@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

Tôi đã viết kịch bản ping google.com cứ sau 5 giây và ghi lại kết quả với thời gian hiện tại. Tại đây bạn có thể tìm đầu ra cho các biến "lệnhLineStr" (có chỉ số)

@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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.