Q:

Parsing special characters in a for loop from a file to a variable

I'm trying to set a variable (Let's say, filehash is the variable name) from a file using batch file. Alas, I was stuck facing these two problems:

When it contains special characters, especially exclamation mark(s) as I'm using enableDelayedExpansion.
While doing that, I need to change &amp; to & as well.

I've tried several solutions provided from various sources but none would fit my requirements.
Here's my current code:
@echo off
set grep=binaries\grep.exe
set fileindex=binaries\index.htm
set count=0
for /f "tokens=* delims=" %%a in (crc.dat) do ( 
set count=!count! + 1
set filehash=%%a
%grep% --ignore-case -w "!filehash!" %fileindex%>> list.dat
)

And an example of what's inside the crc.dat file:
Kabooom! Kablooey!
Kaboom &amp; Kablooey

And the result using my current code above in list.dat:
Kabooom Kablooey
Kaboom &amp; Kablooey

The result that I'm expecting in list.dat:
Kabooom! Kablooey!
Kaboom & Kablooey

I hope I conveyed my problem properly and thank you in advance!

A:

To replace &amp; by & in the input of grep, use this:
@echo off
setlocal EnableExtensions DisableDelayedExpansion

rem // Define constants here:
set "grep=binaries\grep.exe"
set "fileindex=binaries\index.htm"
set "file=crc.dat"
set "list=list.dat"

rem // Initialise counter:
set /A "count=0"
> "%list%" (
    for /F "usebackq delims=" %%a in ("%file%") do (
        rem // Increment counter:
        set /A "count+=1"
        rem // Assign line string to variable:
        set "lineitem=%%a"
        rem // Toggle delayed expansion:
        setlocal EnableDelayedExpansion
        rem // Do sub-string replacement:
        set "lineitem=!lineitem:&amp;=&!"
        rem // Execute `grep` command line:
        "!grep!" --ignore-case -w "!lineitem!" "!fileindex!"
        endlocal
    )
)
rem // Return counter:
echo/%count%

endlocal

To replace &amp; by & in the output of grep, use this:
@echo off
setlocal EnableExtensions DisableDelayedExpansion

rem // Define constants here:
set "grep=binaries\grep.exe"
set "fileindex=binaries\index.htm"
set "file=crc.dat"
set "list=list.dat"

rem // Initialise counter:
set /A "count=0"
> "%list%" (
    for /F "usebackq delims=" %%a in ("%file%") do (
        rem // Increment counter:
        set /A "count+=1"
        rem // Execute `grep` command line and capture its output by `for /F`:
        for /F "delims=" %%b in ('^""%grep%" --ignore-case -w "%%a" "%fileindex%"^"') do (
            rem // Assign `grep` output to variable:
            set "lineitem=%%b"
            rem // Toggle delayed expansion:
            setlocal EnableDelayedExpansion
            rem // Do sub-string replacement:
            set "lineitem=!lineitem:&amp;=&!"
            rem // Return modified string:
            echo(!lineitem!
            endlocal
        )
    )
)
rem // Return counter:
echo/%count%

endlocal

In general, to handle strings with exclamation marks, you must toggle delayed expansion, so that normal %-expanded variables and for variable references like %%a become expanded with delayed expansion disabled.

