How to search and replace a string that have an equal-to sign “=” inside

The following script constitutes a pure solution. Supposing it is stored as repl-str.bat, you need to call it like this for your application:

repl-str.bat "%SettingFile%.txt" "Pippo.K=5" "Pippo.K=1" "%SettingFile%.txt"

This specifies the input file %SettingFile%.txt, the literal and case-sensitive search string Pippo.K=5, the replacement string Pippo.K=1 and the output file %SettingFile%.txt that is the same as the input file (the related technique has been taken from this answer: Batch script to find and replace a string in text file without creating an extra output file for storing the modified file). If no output file is given, the result is output to the console (useful for testing). If a fifth command line argument is given (arbitrary value), the search is done in a case-sensitive manner.

Here is the code of the script repl-str.bat:

@echo off
setlocal EnableExtensions DisableDelayedExpansion

set "FILE_I=%~1"
set "SEARCH=%~2"
set "REPLAC=%~3"
set "FILE_O=%~4"
set "CASE=%~5"
set "FLAG=%~6"
if not defined FILE_I exit /B 1
if not defined SEARCH exit /B 1
if not defined FILE_O set "FILE_O=con"
if defined CASE set "CASE=#"
if defined FLAG set "FLAG=#"

for /F "delims=" %%L in ('
    findstr /N /R "^" "%FILE_I%" ^& break ^> "%FILE_O%"
') do (
    set "STRING=%%L"
    setlocal EnableDelayedExpansion
    set "STRING=!STRING:*:=!"
    call :REPL RETURN STRING SEARCH REPLAC "%CASE%" "%FLAG%"
    >> "%FILE_O%" echo(!RETURN!
    endlocal
)

endlocal
exit /B


:REPL  rtn_string  ref_string  ref_search  ref_replac  case  flag
setlocal EnableDelayedExpansion
set "STR=!%~2!"
set "SCH=!%~3!"
set "RPL=!%~4!"
if "%~5"=="" (set "OPT=/I") else (set "OPT=")
if not defined SCH endlocal & set "%~1=" & exit /B 1
set "SCH_CHR=!SCH:~,1!"
if not "%~6"=="" set "SCH_CHR="
if "!SCH_CHR!"=="=" set "SCH_CHR=" & rem = terminates search string
if "!SCH_CHR!"==""^" set "SCH_CHR=" & rem " could derange syntax
if "!SCH_CHR!"=="%%" set "SCH_CHR=" & rem % ends variable expansion
if "!SCH_CHR!"=="^!" set "SCH_CHR=" & rem ! ends variable expansion
call :LEN SCH_LEN SCH
call :LEN RPL_LEN RPL
set /A RED_LEN=SCH_LEN-1
set "RES="
:LOOP
call :LEN STR_LEN STR
if not defined STR goto :END
if defined SCH_CHR (
    set "WRK=!STR:*%SCH_CHR%=!"
    if %OPT% "!WRK!"=="!STR!" (
        set "RES=!RES!!STR!"
        set "STR="
    ) else (
        call :LEN WRK_LEN WRK
        set /A DFF_LEN=STR_LEN-WRK_LEN-1,INC_LEN=DFF_LEN+1,MOR_LEN=DFF_LEN+SCH_LEN
        for /F "tokens=1,2,3 delims=," %%M in ("!DFF_LEN!,!INC_LEN!,!MOR_LEN!") do (
            rem set "RES=!RES!!STR:~,%%M!"
            if defined WRK set "WRK=!WRK:~,%RED_LEN%!"
            if %OPT% "!STR:~%%M,1!!WRK!"=="!SCH!" (
                set "RES=!RES!!STR:~,%%M!!RPL!"
                set "STR=!STR:~%%O!"
            ) else (
                set "RES=!RES!!STR:~,%%N!"
                set "STR=!STR:~%%N!"
            )
        )
    )
) else (
    if %OPT% "!STR:~,%SCH_LEN%!"=="!SCH!" (
        set "RES=!RES!!RPL!"
        set "STR=!STR:~%SCH_LEN%!"
    ) else (
        set "RES=!RES!!STR:~,1!"
        set "STR=!STR:~1!"
    )
)
goto :LOOP
:END
if defined RES (
    for /F delims^=^ eol^= %%S in ("!RES!") do (
        endlocal
        set "%~1=%%S"
    )
) else endlocal & set "%~1="
exit /B


:LEN  rtn_length  ref_string
setlocal EnableDelayedExpansion
set "STR=!%~2!"
if not defined STR (set /A LEN=0) else (set /A LEN=1)
for %%L in (4096 2048 1024 512 256 128 64 32 16 8 4 2 1) do (
    if defined STR (
        set "INT=!STR:~%%L!"
        if not "!INT!"=="" set /A LEN+=%%L & set "STR=!INT!"
    )
)
endlocal & set "%~1=%LEN%"
exit /B

Basically, this approach takes the first character of the search string and looks it up in the input text. At each match, it is checked whether the whole search string occurs. If so, it is replaced by the replacement string by removing as many characters as the search string consists of, hence avoiding sub-string replacement syntax which fails in case the search string contains =, or the search or the replacement string contains % or !.
However, if the first character of the search string is =, ", % or !, the approach is different, the script checks every single character position for occurrence of the search string then, with the disadvantage of reduced overall performance. If a sixth command line argument is given (arbitrary value), this (slow) mode is forced.

Leave a Comment