I'm having a bit of trouble with a batch script which needs to parse a value out of an config file into a variable.
Suitably anonymised, the relevant line of the file looks like
<?define ProductShortName="Foo" ?>
I want to set a variable to Foo
. The string ProductShortName
is unique enough to get the line with findstr
, but then I have to extract the value. The correct approach seems to be for /F
, but all of the following give errors:
for /F "delims=^" usebackq" %%G in (`findstr /L "ProductShortName" "%~dp0Installer\Branding.wxi"`) for /F "delims="" usebackq" %%G in (`findstr /L "ProductShortName" "%~dp0Installer\Branding.wxi"`) for /F "delims=\" usebackq" %%G in (`findstr /L "ProductShortName" "%~dp0Installer\Branding.wxi"`) for /F 'delims=^" usebackq' %%G in (`findstr /L "ProductShortName" "%~dp0Installer\Branding.wxi"`) for /F 'delims=" usebackq' %%G in (`findstr /L "ProductShortName" "%~dp0Installer\Branding.wxi"`) for /F "delims=" usebackq" %%G in (`findstr /L "ProductShortName" "%~dp0Installer\Branding.wxi"`)
mostly along the lines of
usebackq" %G in (`findstr /L "ProductShortName" "C:\foo\bar\Installer\Branding.wxi"`) was unexpected at this time.
What's the correct way of escaping it to split the string on "
?
FOR /F processing of a command consists of reading the output from the command one line at a time and then breaking the line up into individual items of data or 'tokens'. The DO command is then executed with the parameter(s) set to the token(s) found.
Escape every double quote " with a caret ^ . If you want other characters with special meaning to the Windows command shell (e.g., < , > , | , & ) to be interpreted as regular characters instead, then escape them with a caret, too.
You can use the double quotation mark as a delimiter with syntax like:
FOR /F delims^=^"^ tokens^=2 %G IN ('echo I "want" a "pony"') DO @ECHO %G
When run on the command line, using tokens^=2
should give you want
, and 4 tokens gets you a pony.
Applying the technique to your original question, this should work in your batch file:
FOR /F delims^=^"^ tokens^=2 %%G IN ('FINDSTR /L "ProductShortName" "data.txt"')
Details
I'm no expert on quirks of the command line parser, but it may help to think of the usual "delims=blah tokens=blah"
as a single, combined argument passed to FOR. The caret escaping trick in delims^=blah^ tokens^=blah
bypasses the need for enclosing quotes while still treating the sequence as a single argument. I've used a bit of creative analogy here, and the effect isn't universal across the shell. E.g. you can't do dir C:^\Program^ Files
(which makes sense since ^
is a valid filename character).
Test Cases
With sufficient escaping, you can quickly check your original sample on the command line:
FOR /F delims^=^"^ tokens^=2 %G IN ('echo ^^^<?define ProductShortName="Foo" ?^^^>') DO @ECHO %G
Others playing with this may want to create a file testcases.txt:
blah blah "red" blah "green" blah How about a "white" "unicorn"?
and run something like:
FOR /F delims^=^"^ tokens^=2 %G IN (testcases.txt) DO @ECHO %G
to check results for a variety of inputs. In this case it should yield:
red green white
One last example:
FOR /F delims^=^"^ tokens^=2 %G IN ('FINDSTR /L "unicorn" "testcases.txt"') ^ DO @ECHO The unicorn is %G.
Finally, note my testing for this was done on Windows Server 2003.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With