2

I have this batch script which flips through 5 static set variables containing a file path to an INI file which it then reads and searches for a specific string to replace.

My issue is that after if does said replacements and writes the file back to the disk, it seems to be sanitizing all instances of ! within the INI file which in turn breaks my program.

I am guessing the ! marks are being replaced due to DelayedExpansion but I need it to perform my tasks here. I am including a copy of the function with the issue, I would be very appreciative if someone could help me figure this out.

I have been stuck trying to find an answer to this for days now…

FOR %%A IN (1 2 3 4 5) DO (
    SET CFG_A=!CFG_%%A!
    IF "%DEBUG%"=="1" ECHO !CFG_A!
    FOR /f "delims=" %%i IN ('type "!CFG_A!" ^& break ^> "!CFG_A!" ') DO (
        SET "line=%%i"
        SETLOCAL enabledelayedexpansion
        SET "line=!line:%IP_V%=%IP%!"
        >>"!CFG_A!" echo(!line!
        ENDLOCAL
    )
)
Giacomo1968
  • 55,001
Pyr3x
  • 23

1 Answers1

1

You obviously have delayed expansion throughout the entire posted code, and delayed expansion occurs after FOR variable expansion. So yes, the value of %%i is corrupted because delayed expansion is enabled.

One solution is to put an extra SETLOCAL / ENDLOCAL within your inner loop to temporarily disable delayed expansion while %%i is expanded.

Also, there is no need to TYPE the file, and no need for the odd redirected BREAK to create an empty output file, or the appending redirection within the loop. You can simply let FOR /F read the file directly, and redirect once outside the inner loop. Granted, you must write to a temporary new file, and then move the result to the original name. But this is much more efficient (faster).

FOR %%A IN (1 2 3 4 5) DO (
  IF "%DEBUG%"=="1" >&2 ECHO(!CFG_%%A!
  (FOR /f "usebackq delims=" %%i IN ("!CFG_%%A!") DO (
    SETLOCAL disableDelayedExpansion
    SET "line=%%i"
    SETLOCAL enableDelayedExpansion
    SET "line=!line:%IP_V%=%IP%!"
    echo(!line!
    ENDLOCAL
    ENDLOCAL
  ))>"!CFG_%%A!.new"
  MOVE /Y "!CFG_%%A!.new" "!CFG_%%A!" >nul
)

Note - I really dislike editing text files via batch. Instead, I would use JREPL.BAT - a hybrid JScript/batch utility that runs natively on any Windows machine from XP onward:

FOR %%A IN (1 2 3 4 5) DO CALL JREPL "%IP_V%" "%IP%" /L /I /F "!CFG_%%A!" /O -

Much simpler, and faster, and more reliable :-)

dbenham
  • 11,384
  • This worked out really well! Thank you very much! I was able to apply it to my code and I also have a firm understanding of why you did what you did. As for the questions pertaining to the use of "break" I have to admit that even I didn't fully understand it. I had been given the solution for that by a friend of mine and my basic understanding of it after spending a great deal of time messing with it is that it edits the data in memory and then writes it over the file after but I'm not sure. – Pyr3x Sep 17 '15 at 22:43
  • Dave - When you get a chance, just in case you have any tips on the topic with this question "My Question" I wanted to send you a link just in case. There may not be much to this other than what others have already said but I figured if anyone had any additional helpful tips, it'd be you. Keep up your great work, man!! – Vomit IT - Chunky Mess Style Aug 09 '16 at 01:30