This batch code works for the example to toggle in line with ISDEV
the value false
to true
or the value true
to false
.
@echo off
if "%~1" == "" goto :EOF
if not exist Input.txt goto :EOF
setlocal EnableExtensions EnableDelayedExpansion
set "SearchString=%~1"
set "TextFile=Input.txt"
set "TempFile=%TEMP%\%~n0.tmp"
del "%TempFile%" 2>nul
for /F "usebackq delims=" %%I in ("%TextFile%") do (
set "Line=%%I"
if not "!Line:%SearchString%=!" == "!Line!" (
for /F "tokens=2 delims=;=" %%J in ("!Line!") do (
for /F %%V in ("%%~J") do set "Value=%%V"
)
if "!Value!" == "false" (
set "Line=!Line:false=true!"
) else if "!Value!" == "true" (
set "Line=!Line:true=false!"
)
)
echo !Line!>>"%TempFile%"
)
move /Y "%TempFile%" "%TextFile%" >nul 2>&1
if errorlevel 1 del "%TempFile%"
endlocal
But a batch file solution is in general a bad idea for this task. Windows command line interpreter is not designed for string changes in text files. It is designed to execute commands and applications. There are lots of script interpreters which are better for making changes in text files like VBScript, JScript, PowerShell, Python, Perl, ...
The batch file above reads each non empty line not starting with a semicolon from file Input.txt
and assigns it to environment variable Line
whereby everything between two exclamation marks with both !
or from an exclamation mark to end of line are removed on command line set "Line=%%I"
because of enabled delayed environment variable expansion. In other words this batch file cannot be used to process a text file containing empty lines, lines starting with ;
and lines containing one or more !
.
The IF condition checks if the line contains the search string passed with argument 1 to the batch file by comparing the line with all occurrences of search string substituted case-insensitive by an empty string with the unmodified line. The two compared strings are not equal if the line contains the search string at least once.
In case of line really contains ISDEV
, one more FOR is used to get the string after first occurrence of an equal sign or a semicolon assigned to loop variable J
.
A third FOR loop is used to remove all spaces/tabs around the value read from file.
If the remaining value is case-sensitive either false
or true
, the appropriate string substitution is executed to replace all false
case-insensitive in the line by true
or all true
by false
.
The unmodified or modified line is output and this output is redirected into a temporary file which is finally moved over input file.
Here is one more batch file which is much slower as above. It replaces the current value by the string specified as second argument. And it handles lines containing an exclamation mark correct.
@echo off
if "%~1" == "" goto :EOF
if "%~2" == "" goto :EOF
if not exist Input.txt goto :EOF
setlocal EnableExtensions DisableDelayedExpansion
set "SearchString=%~1"
set "NewValue=%~2"
set "TextFile=Input.txt"
set "TempFile=%TEMP%\%~n0.tmp"
del "%TempFile%" 2>nul
for /F "usebackq delims=" %%I in ("%TextFile%") do (
set "Line=%%I"
call :ProcessLine
)
move /Y "%TempFile%" "%TextFile%" >nul 2>&1
if errorlevel 1 del "%TempFile%"
endlocal
rem Avoid a fall through to subroutine below.
goto :EOF
:ProcessLine
setlocal EnableDelayedExpansion
if "!Line:%SearchString%=!" == "!Line!" goto OutputLine
for /F "tokens=2 delims=;=" %%J in ("!Line!") do (
for /F %%V in ("%%~J") do set "OldValue=%%V"
)
set "Line=!Line:%OldValue%=%NewValue%!"
:OutputLine
echo !Line!>>"%TempFile%"
endlocal
goto :EOF
But this batch file skips also all empty lines and lines starting with ;
.
This third batch file keeps empty lines and lines starting with ;
.
@echo off
if "%~1" == "" goto :EOF
if "%~2" == "" goto :EOF
if not exist Input.txt goto :EOF
setlocal EnableExtensions DisableDelayedExpansion
set "SearchString=%~1"
set "NewValue=%~2"
set "TextFile=Input.txt"
set "TempFile=%TEMP%\%~n0.tmp"
del "%TempFile%" 2>nul
for /F "tokens=1* delims=:" %%I in ('%SystemRoot%\System32\findstr.exe /R /N /C:"^" "%TextFile%" 2^>nul') do (
set "Line=%%J"
if not defined Line echo/>>"%TempFile%"
if defined Line call :ProcessLine
)
move /Y "%TempFile%" "%TextFile%" >nul 2>&1
if errorlevel 1 del "%TempFile%"
endlocal
rem Avoid a fall through to subroutine below.
goto :EOF
:ProcessLine
setlocal EnableDelayedExpansion
if "!Line:%SearchString%=!" == "!Line!" goto OutputLine
for /F "tokens=2 delims=;=" %%K in ("!Line!") do (
for /F %%V in ("%%~K") do set "OldValue=%%V"
)
set "Line=!Line:%OldValue%=%NewValue%!"
:OutputLine
echo !Line!>>"%TempFile%"
endlocal
goto :EOF
But lines starting with one or more :
are in modified Input.txt
without the colon(s) at beginning of the line.
Finally let us look on how easy string replaces in text files can be on using the right scripting language, for example JScript installed also with Windows which supports regular expression replaces.
We are using JREPL.BAT written by Dave Benham which is a batch file / JScript hybrid to run a regular expression replace on a file using JScript stored in same directory as the batch file below.
@echo off
if "%~1" == "" goto :EOF
if "%~2" == "" goto :EOF
if not exist Input.txt goto :EOF
call "%~dp0jrepl.bat" "(%~1[ \t]*=[ \t]*)[^;]+" "$1%~2" /F "Input.txt" /O -
It would be of course possible to do the entire task with cscript.exe
or wscript.exe
and an appropriate script file or powershell.exe
and an appropriate PowerShell script.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
call /?
... explains %~n0
(name of batch file without path and extension)
del /?
echo /?
endlocal /?
findstr /?
for /?
goto /?
if /?
move /?
rem /?
set /?
setlocal /?
jrepl.bat /? | more
Read also the Microsoft article about Using Command Redirection Operators and answer on Where does GOTO :EOF return to?