string replacer for 1 file but it needs looping to replace many OldStrings with NewStrings

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
nnnmmm
Posts: 184
Joined: 26 Aug 2017 06:11

string replacer for 1 file but it needs looping to replace many OldStrings with NewStrings

#1 Post by nnnmmm » 17 Mar 2025 19:55

a difficult part of updating a software is NOT replacing an EXE or DLLs
it is about how to re-modify INI and CONF again whose filesizes vary from 50k ~ 250K frequently, finding target strings causes a lot of headache in large files. i hope to put an end to this, my initial batch drawing board looks like this below.

Code: Select all

@ECHO OFF
Setlocal EnableExtensions DisableDelayedExpansion
FOR %%V IN (
    "cycles             = auto" "cycles             = max" 
    "time    = 1"               "time    = 3"
    "ShowNavPanel=true"         "ShowNavPanel=false" 
    "ShowBottomPanel=true"      "ShowBottomPanel=false"
    "ShowZoomNavigator=true"    "ShowZoomNavigator=false"
    "ZoomPausePercent=100"      "ZoomPausePercent=0"  
 
) DO (
   "STRING REPLACER.EXE"  "%oldstring%" "%newstring%" %1
)
:END
pause
%1 means an input filename

these are old strings
"cycles = auto"
"time = 1"
"ShowNavPanel=true"
"ShowBottomPanel=true"
"ShowZoomNavigator=true"
"ZoomPausePercent=100"

these are new strings
"cycles = max"
"time = 3"
"ShowNavPanel=false"
"ShowBottomPanel=false"
"ShowZoomNavigator=false"

Aacini
Expert
Posts: 1923
Joined: 06 Dec 2011 22:15
Location: México City, México
Contact:

Re: string replacer for 1 file but it needs looping to replace many OldStrings with NewStrings

#2 Post by Aacini » 19 Mar 2025 17:31

Ok. There are a couple important details in this problem.

The code below is designed to run fast with large input files. The input file is processed each time with one find string and just in the lines that contains the find string . The rest of the input lines are just copied as fast as possible. This should run faster that if we look for all find strings in each line of the input file. Besides, if we process a large input file via FOR /F command then there will be additional buffer/time problems.

Another important problem is the replacement of a string that contains equals signs. There is not a simple nor fast method to do so. In this solution a trick is used: I assumed that the input line just contains the find string enclosed in quotes, so the output is comprised of just the replacement string enclosed in quotes. This way, we do NOT use the Batch !line:%find%=%repl%! string replacement. If this point is required, the method needs to be modified.

Finally, in the example it is not clear if a find string can contain several (variable number of) blank spaces. If this point is important, a modification is needed.

Code: Select all

@echo off
setlocal EnableDelayedExpansion

set "file=test.txt"

set "find="
for %%a in (
    "cycles = auto"             "cycles = max" 
    "time = 1"                  "time = 3"
    "ShowNavPanel=true"         "ShowNavPanel=false" 
    "ShowBottomPanel=true"      "ShowBottomPanel=false"
    "ShowZoomNavigator=true"    "ShowZoomNavigator=false"
    "ZoomPausePercent=100"      "ZoomPausePercent=0"  
) do (
   if not defined find (
      set "find=%%~a"
   ) else (
      set "lastLine=0"
      < "%file%" (
         for /F "delims=:" %%i in ('findstr /N /C:"!find!" "%file%"') do (
            set /A "skip=%%i-lastLine-1, lastLine=%%i"
            for /L %%s in (1,1,!skip!) do (
               set "line="
               set /P "line="
               echo(!line!
            )
            set /P "line="
            echo "%%~a"
         )
         findstr "^"
      ) > temp.tmp
      move /Y temp.tmp "%file%" > NUL
      set "find="
   )
)
Antonio

nnnmmm
Posts: 184
Joined: 26 Aug 2017 06:11

Re: string replacer for 1 file but it needs looping to replace many OldStrings with NewStrings

#3 Post by nnnmmm » 27 Mar 2025 02:26

thanks it worked well, you actually make the SR.EXE (string replacer.exe) in your script. and i tried to make a subroutine out of it CALL :SR FILE "%%~a", it also worked but AA='s ECHO %FIND% has different strings than BB='s ECHO %FIND%, i spent several hours to find the reason, but none found by the trial and error method but i just accepted that it worked at the end.

SR.EXE (string replacer.exe) works even when input data contains \ and % and ^ except for ""

>Another important problem is the replacement of a string that contains equals signs
it worked with the input data that have =s

>Finally, in the example it is not clear if a find string can contain several (variable number of) blank spaces.
so i tried below and all worked

Code: Select all

"ZoomP ause    Percent=100"    "ZoomPausePercent = 0"
"ZoomP           ause    Percent=100"    "ZoomPaus    ePercent=0"
"Zoom P       a           use    Perc    ent  =        100"    "ZoomP      ausePercent=0"
dosbox uses cycles (how many spaces) = (how many spaces) 1, "how many spaces" are all different from file to file so i havent used it on dosbox's conf yet

AA=

Code: Select all

@echo off
setlocal EnableDelayedExpansion

set "file=JPEGView.ini"

set "find="
for %%a in (
   "Units=auto"                      "Units=metric"
   "SlideShowTransitionEffect=Blend" "SlideShowTransitionEffect=None"
   "SlideShowEffectTime=250" "SlideShowEffectTime=1"
   "ShowNavPanel=true"       "ShowNavPanel=false"
   "ShowBottomPanel=true"    "ShowBottomPanel=false"
   "ShowZoomNavigator=true"  "ShowZoomNavigator=false"
   "AllowFileDeletion=true"  "AllowFileDeletion=false"
   "SkipFileOpenDialogOnStartup=false" "SkipFileOpenDialogOnStartup=true"
   "ZoomPausePercent=100"    "ZoomPausePercent=0"

   "AutoZoomMode=FitNoZoom"  "AutoZoomMode=Fill"
   "ShowFullScreen=auto"     "ShowFullScreen=false"
   "DefaultWindowRect=image" "DefaultWindowRect=19 1 504 1050" 
) do (
   CALL :SR FILE "%%~a"
)
GOTO :END

:SR
   if not defined find (
      set "find=%2"
   ) else (
      set "lastLine=0"
      SET "FILE=%~1"

[b]ECHO %FIND%[/b]
PAUSE

      < "%file%" (
         for /F "delims=:" %%i in ('findstr /N /C:"!find!" "%file%"') do (
            set /A "skip=%%i-lastLine-1, lastLine=%%i"
            for /L %%s in (1,1,!skip!) do (
               set "line="
               set /P "line="
               echo(!line!
            )
            set /P "line="
            echo %%~a
         )
         findstr "^"
      ) > temp.tmp
      move /Y temp.tmp "%file%" > NUL
      set "find="
      set "%1=%FILE%"
   )
EXIT /B
:END
*****************************************************************
BB=

Code: Select all

@echo off
setlocal EnableDelayedExpansion

set "file=JPEGView.ini"

set "find="
for %%a in (
   "Units=auto"                      "Units=metric"
   "SlideShowTransitionEffect=Blend" "SlideShowTransitionEffect=None"
   "SlideShowEffectTime=250" "SlideShowEffectTime=1"
   "ShowNavPanel=true"       "ShowNavPanel=false"
   "ShowBottomPanel=true"    "ShowBottomPanel=false"
   "ShowZoomNavigator=true"  "ShowZoomNavigator=false"
   "AllowFileDeletion=true"  "AllowFileDeletion=false"
   "SkipFileOpenDialogOnStartup=false" "SkipFileOpenDialogOnStartup=true"
   "ZoomPausePercent=100"    "ZoomPausePercent=0"

   "AutoZoomMode=FitNoZoom"  "AutoZoomMode=Fill"
   "ShowFullScreen=auto"     "ShowFullScreen=false"
   "DefaultWindowRect=image" "DefaultWindowRect=19 1 504 1050" 
) do (
   if not defined find (
      set "find=%%~a"
   ) else (

[b]ECHO %FIND%[/b]
PAUSE

      set "lastLine=0"
      < "%file%" (
         for /F "delims=:" %%i in ('findstr /N /C:"!find!" "%file%"') do (
            set /A "skip=%%i-lastLine-1, lastLine=%%i"
            for /L %%s in (1,1,!skip!) do (
               set "line="
               set /P "line="
               echo(!line!
            )
            set /P "line="
            echo %%~a
         )
         findstr "^"
      ) > temp.tmp
      move /Y temp.tmp "%file%" > NUL
      set "find="
   )
)

Post Reply