Search code examples
batch-filecmdfindstr

Escaping exclamation marks with delayed expansion


I have a batch file I'm using to search for a piece of text and replace it with another. It works, but what's happening is that when the 'new' file is created, anything after an exclamation mark is deleted.

So original file

Hello! I have some cheese

Just becomes

Hello

Although the text I am trying to replace is fine.

I understand that since I'm using delayed expansion I need to somehow escape the exclamation marks with ^^! but can't figure out where to do this. Adding it at the echo just echoes the ^^! literally.

Any help would be appreciated.

set "rootname=Common Filename"

set "replace="old">"
set "replaced="new">"


set "source="%rootname%_unqiue_suffix.txt""
set "target=Fixed\%SOURCE%"


 setlocal enableDelayedExpansion
(
   for /F "tokens=1* delims=:" %%a in ('findstr /N "^" %source%') do (
      set "line=%%b"
      if defined line set "line=!line:%replace%=%replaced%!"
      echo(!line!
   )
) > %target%

endlocal

Solution

  • To avoid loss of exclamation marks, enable delayed expansion only when it is really needed and expand normal % variables and for meta-variables only when delayed expansion is disabled:

    @echo off
    setlocal EnableExtensions DisableDelayedExpansion
    set "rootname=Common Filename"
    
    set "replace="old">"
    set "replaced="new">"
    
    set "source=%rootname%_unqiue_suffix.txt"
    set "target=Fixed\%source%"
    
    (
        for /F "tokens=1* delims=:" %%a in ('findstr /N "^" "%source%"') do (
            set "line=%%b"
            setlocal EnableDelayedExpansion
            if defined line set "line=!line:%replace%=%replaced%!"
            echo(!line!
            endlocal
        )
    ) > "%target%"
    
    endlocal
    

    This code still causes trouble in case the variables replace and replaced contain !-signs, because they are percent-expanded.