This PowerShell code selects the correct value for var5
from this string. The desired result it \"Alert Raised\".
PS C:\\src\\t> $s = \'Statu
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.
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.
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.