Capture output from a PowerShell command in a batch file's for /f loop

前端 未结 2 2090
我寻月下人不归
我寻月下人不归 2021-01-17 01:35

This PowerShell code selects the correct value for var5 from this string. The desired result it \"Alert Raised\".

PS C:\\src\\t> $s = \'Statu         


        
相关标签:
2条回答
  • 2021-01-17 02:05

    PetSerAl, as he often does, has provided the crucial pointer in a comment:

    cmd.exe's for /f loop by default breaks its input lines into tokens by whitespace, so that for /f %%a in (...) do only places the first such token in variable %%a.

    This default behavior can be modified with an options string: for /f "<options>" %%a in (...) do.
    Running for /? from a cmd.exe prompt describes its syntax:

        eol=c           - specifies an end of line comment character
                          (just one)
        skip=n          - specifies the number of lines to skip at the
                          beginning of the file.
        delims=xxx      - specifies a delimiter set.  This replaces the
                          default delimiter set of space and tab.
        tokens=x,y,m-n  - specifies which tokens from each line are to
                          be passed to the for body for each iteration.
                          This will cause additional variable names to
                          be allocated.  The m-n form is a range,
                          specifying the mth through the nth tokens.  If
                          the last character in the tokens= string is an
                          asterisk, then an additional variable is
                          allocated and receives the remaining text on
                          the line after the last token parsed.
        usebackq        - specifies that the new semantics are in force,
                          where a back quoted string is executed as a
                          command and a single quoted string is a
                          literal string command and allows the use of
                          double quotes to quote file names in
                          file-set.
    

    If you want each input line to be captured in a single variable, you have two options:

    Note: The examples below use the following PowerShell command line, which simply outputs a string literal with multiple leading, inner, and trailing spaces,   one two  .

    powershell -command " '   one   two   ' "
    

    To make quoting easier, option usebackq is used below, which allows embedding the command in `...`.

    Also note that it's good practice to add -NoProfile to powershell.exe's command line to prevent unnecessary - and potentially behavior-changing - loading of a user's profile; I've omitted it below for brevity.


    "delims=": preserving the line exactly as-is

    @echo off
    
    for /f "usebackq delims=" %%a in (`powershell -command " '   one   two   ' "`) do echo Result is "%%a"
    

    The above yields:

    Result is "   one   two   "
    

    Note how the leading and trailing spaces were preserved too.

    Important: for delims= to be recognized as deactivating delimiter-based (separator-based) parsing, it must be placed at the very end of the options string.


    "tokens=*": trimming leading whitespace

    @echo off
    
    for /f "usebackq tokens=*" %%a in (`powershell -command " '   one   two   ' "`) do echo Result is "%%a"
    

    The above yields:

    Result is "one   two   "
    

    Note how the leading spaces were trimmed.

    It is curious that the trimming is only applied to leading whitespace, and there appears to be no direct way to trim trailing whitespace as well.

    0 讨论(0)
  • 2021-01-17 02:06

    You don't need the for loop in the batch file.

    @ECHO OFF
    SET "S=Status 58   var5=Alert Raised on: March"
    powershell -NoLogo -NoProfile -Command " '%S%' | Where-Object { $_ -match '.*var5=(.*)\s+\w+:' } | ForEach-Object { $Matches[1] } "
    

    The above gives the expected result.

    0 讨论(0)
提交回复
热议问题