FrankS101
FrankS101

Reputation: 2135

Append a string in a file after another string through a windows batch file

I'm trying to write a batch file to append a certain string "str2 => bbb" to a file if it is not yet present in the file. "str2" will go after the string "str1 => aaa" (that always exists in the file). For example:

file.txt

...

str1 => aaa

...

end of file.txt

it will become:

file.txt

...

...

...

str1 => aaa

str2 => bbb

...

end of file.txt

and the batch file must be not destructive, i.e. if "str2" already exists in the file, the batch will do nothing.

I know how to find a string in the file:

FINDSTR "str2 => bbb" "file.txt"

IF %errorlevel%==0 (
    ECHO FOUND
) 

but I don't know what else to do to write the other string in the next line.

Upvotes: 2

Views: 1913

Answers (2)

aschipfl
aschipfl

Reputation: 34899

Since it is not clear to me whether str2 must occur immediately after str1 in the file or just anywhere, I wrote the following script which is capable of covering both criterias. It directly modifies the input file in case, so be careful. The input file must be speficied as a command line argument:

@echo off
setlocal EnableExtensions DisableDelayedExpansion

rem // Define constants here:
set "FILE=%~1" & rem // (input file; `%~1` takes first command line argument)
set "WORD1=str1" & rem // (word after which `%WORD2%` must be inserted)
set "WORD2=str2" & rem // (word that must be present in the file)
set "STRING2=%WORD2% => bbb" & rem // (full string to insert if `%WORD2%` is missing)
set "SEPARATORS=    = " & rem // (characters that separate the words from the rest)
set "FIXEDPOS=#" & rem // (if not empty, defines that `%WORD2%` must be after `%WORD1%`)

rem // Create line-break (carriage-return and line-feed):
(for /F %%# in ('copy /Z "%~f0" nul') do set ^"CR+LF=%%#^
%= empty line =%
^")

rem // Ensure list of separators contains (ends) with space:
if defined SEPARATORS (
    if not "%SEPARATORS:~-1%"==" " set "SEPARATORS=%SEPARATORS: =% "
) else set "SEPARATORS= "
setlocal EnableDelayedExpansion
rem // Set up regular expression:
if defined FIXEDPOS (
    rem /* `%WORD2%` must be in the line following `%WORD1%`, so define a dual-line
    rem    regular expression (both words must be present at the beginnings of lines): */
    set "REGEX=^%WORD1%[%SEPARATORS%].*!CR+LF!%WORD2%[%SEPARATORS%]"
) else (
    rem /* Position of `%WORD2%` does not matter with respect to `%WORD1%`,
    rem    hence it merely must be present at the beginning of a line: */
    set "REGEX=^%WORD2%[%SEPARATORS%]"
)
rem // Search for regular expression in file:
> nul findstr /I /R /C:"!REGEX!" "%FILE%" || (
    rem // No match encountered, so read entire file and deplete it afterwards:
    for /F "delims=" %%L in ('findstr /N /R "^" "%FILE%" ^& ^> "%FILE%" break') do (
        endlocal
        rem // Read a line, reset flag that defines whether or not to insert a string:
        set "FLAG=" & set "LINE=%%L"
        setlocal EnableDelayedExpansion
        rem // Split off first word and compare with `%WORD1%`:
        for /F "eol=  tokens=1 delims=%SEPARATORS%" %%K in ("!LINE:*:=!") do (
            endlocal
            rem // First word matches `%WORD1%`, so set flag:
            if /I "%%K"=="%WORD1%" set "FLAG=#"
            setlocal EnableDelayedExpansion
        )
        rem // Append to file:
        >> "%FILE%" (
            rem // Write original line:
            echo(!LINE:*:=!
            rem // Write string to insert in case flag is defined:
            if defined FLAG echo(!STRING2!
        )
    )
)
endlocal

endlocal
exit /B

Note that this script does not check whether str1 occurs multiple times.

Upvotes: 1

Cividan
Cividan

Reputation: 108

Use powershell in your batch file to simplify things

    FINDSTR "str2 => bbb" "file.txt"

    IF %errorlevel%==0 (
        ECHO FOUND
        Goto END
    )
    powershell -Command "(get-content File.txt) -replace "str1 => aaa", "$&`n str2 => bbb" | set-content File.txt"
:end

The powershell command will get the content of your file and replace your string with search string ($&) + new line + str2...)

Upvotes: 0

Related Questions