1

I'm having trouble figuring out a way to remove a substring from a string when both may have reserved characters in it. Nothing I've attempted has had any luck.

I'm new to batch, but right now I'm using the methods described here, with modifications: String replacement in batch file

Here's my code sample, but it doesn't work at all with ! or : in the strings:

:: NOT WORKING
:RemoveWordsFromFileInLine

    :: %1 string to remove
    :: %2 source file
    :: %3 destination file

    setlocal enabledelayedexpansion    
    :: Loop through each "word" of every "line"
    set "toReplace=%1 "
    set "blank="

    del %3
    for /F "tokens=* delims=" %%a in (%2) do (    
    setlocal disabledelayedexpansion    
        echo "line=%%a"
        echo line is %line%

    setlocal enabledelayedexpansion    
        set "newLine=!line:%toReplace%=%blank%!"
        echo newLine is !newLine!
        @echo !newLine! >>%3
    endlocal    
    )

    if exist %3 ( move /y %3 %2 >nul )

GOTO:EOF

As you can see, I've tried disabling delayed expansion on the "set" of my line variable, but I can't do that in the replacement section itself.

Some example strings in the file are:

<!-- XML Comment goes here -->
<planets> Mars world:Earth </planets>
<planets> Venus Earth Mercury </planets>

Some example strings I'd look to replace are:

world:Earth
Earth

Anyone have any ideas on how I could make the string replacement work? I've tried numerous things, usually involving putting double quotes in various places (like around the line variable in the string replace statement), but I haven't had any luck yet.

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
Charles S.
  • 11
  • 4
  • `set "newLine=!%%a:%toReplace%=%blank%!"` --> `set "newLine=!line:%toReplace%=%blank%!"` – aschipfl Aug 27 '18 at 18:46
  • Sorry, yeah, that's how I used to have it. I had edited it in my attempts to fix and forgot to revert that portion. Thanks for catching that. – Charles S. Aug 27 '18 at 18:49
  • Actually, that helped it a bit... the early strings in the file (including the – Charles S. Aug 27 '18 at 18:53
  • Interesting, looks like I hit "Maximum setlocal recursion level reached." in my log... so I guess that's an entirely different question. – Charles S. Aug 27 '18 at 19:03
  • Ah yes, you've got unbalanced `setlocal`/`endlocal` in your loop; I'd change the very first one (outside of the loop) to `setlocal DisableDelayedExsansion` and remove the second one (already in the loop), then it should be fine. Of course the line `echo line is %line%` in the loop can't work; it should be changed to `echo line is !line!` and moved below `setlocal EnableDelayedExpansion`... – aschipfl Aug 27 '18 at 19:07
  • Thanks for that - I ended up using a second endlocal as well just to keep them balanced completely. I just removed the echoes since they were only there for debugging - thanks so much for your help! I guess if you stare at something long enough you start missing obvious issues. Very glad to have had the extra eyes. – Charles S. Aug 27 '18 at 19:37

1 Answers1

0

So thanks to aschipfl for helping me figure this out; My main issues came down to poor usage of setlocal / endlocal. I'm pretty sure mucking this up is what's caused all my attempts to fail.

Final Code ended up:

:RemoveWordsFromFileInLine

    :: %1 string to remove
    :: %2 source file
    :: %3 destination file

    setlocal disabledelayedexpansion    
    :: Loop through each "word" of every "line"
    set "toReplace=%1 "
    set "blank="

    del %3
    for /F "tokens=* delims=" %%a in (%2) do (

        set "line=%%a"

    setlocal enabledelayedexpansion    
        set "newLine=!line:%toReplace%=%blank%!"
        @echo !newLine! >>%3
    endlocal    
    )
    endlocal    

    if exist %3 ( move /y %3 %2 >nul )

GOTO:EOF

Biggest things to note (as I understand them):

  • Setting the line var requires disabledelayedexpansion, otherwise it will try to parse the ! in the line
  • Setting enabledelayedexpansion to be on is required for the replace functionality because we need to know what value of line is at that point of the loop.
Charles S.
  • 11
  • 4