Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Escaping double-quote in `delims` option of `for /F`

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 "?

like image 897
Peter Taylor Avatar asked Sep 22 '11 14:09

Peter Taylor


People also ask

What is F in batch script?

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.

How do I escape a double quote in Windows command line?

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.


1 Answers

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.

like image 78
rkagerer Avatar answered Sep 27 '22 16:09

rkagerer