Nbl123
Nbl123

Reputation: 45

loop through a text file and insert a line with batch file

I am trying to search through a text file for keywords, then insert a number of lines after a specific line/keyword (not end of file).

My code can find the keywords, however I am struggling to add the lines. My code adds the line to the end of the file, so the bit I need help with is after :ADD THE TEXT.

myfile.text looks like:

QFU;
text2;
LastUpdate=20180323;
text3;

I would like to add a list of static lines after LastUpdate, which makes the file look like:

QFU;
text2;
LastUpdate=20180323;
Inserted text1
Inserted text2
text3;

This is my code:

@echo

SET /A COND1=0

for /F "tokens=*" %%i in (myfile.txt) do call :process %%i
goto thenextstep
:process
set VAR1=%1
IF "%VAR1%"=="QFU" SET /A COND1=1
IF "%VAR1%"=="QFU" (
msg * "QFU line found !!"
)
:If QFU line is found then look for Last update
IF "%COND1%"=="1" IF "%VAR1%"=="LastUpdate" (
msg * "LastUpdate line found !!"

:ADD THE TEXT
echo. text to be added>>myfile.txt

:reset COND1 to 0
set /A COND1=0
)

Upvotes: 0

Views: 1677

Answers (1)

michael_heath
michael_heath

Reputation: 5372

@echo off
setlocal enabledelayedexpansion

call :get_insert_index

if not defined index (
    >&2 echo index not defined.
    exit /b 1
)

set "i=0"

(
    for /f "tokens=*" %%A in (myfile.txt) do (
        set /a "i+=1"
        echo %%A

        for %%B in (%index%) do if !i! equ %%B (
            echo --- INSERT
        )
    )
) > myupdate.txt

exit /b

:get_insert_index
setlocal enabledelayedexpansion

set "i=0"
set "qfu="
set "total="

for /f "tokens=*" %%A in (myfile.txt) do (
    set /a i+=1
    set "line=%%~A"

    if "%%~A" == "QFU;" (
        set /a "qfu=!i! + 1"
    ) else if "!line:~,11!" == "LastUpdate=" (
        if defined qfu (
            if !i! gtr !qfu! (
                if defined total (set total=!total! !i!) else set total=!i!
                set "qfu="
            )
        )
    )
)
endlocal & set "index=%total%"
exit /b

This will insert text after the 1st line starting with LastUpdate=, after the line of QFU;, but not the line starting with LastUpdate= which is the next line after QFU;.

The label :get_insert_index is called and uses a for loop to read myfile.txt to get the line index of LastUpdate= mentioned in the above paragraph. The variable qfu stores the line index + 1 of QFU; so LastUpdate= cannot be matched on the next line. If gfu and LastUpdate= is found and the line index is greater then gfu, then the line index is appended to total. qfu is undefined to avoid further matches to LastUpdate= until QFU; is matched again. The loop will end and the global variable index is set the value of total. The label returns control back to the caller.

index is checked if defined at the top of the script after the call of the label. The top for loop reads myfile.txt and echoes each line read. The nested for loop checks the index variable to match the current line index and if equal, will echo the new text. The echoes are redirected to myupdate.txt.

Used substitution of "!line:~,11!" so view set /? for help.

Used enabledelayedexpansion so view setlocal /? for help. Text using ! may find ! being interpreted as a variable so avoid using !.

Used gtr which can be viewed in if /?. gtr is "Greater than".


Alternative to avoid creation of an index:

@echo off
setlocal enabledelayedexpansion

set "i=0"
set "gfu="

for /f "tokens=*" %%A in (myfile.txt) do (
    set /a i+=1
    set "line=%%~A"

    >> myupdate.txt echo(%%A

    if "%%~A" == "QFU;" (
        set /a "qfu=!i! + 1"
    ) else if "!line:~,11!" == "LastUpdate=" (
        if defined qfu (
            if !i! gtr !qfu! (
                >> myupdate.txt echo --- INSERT
                set "qfu="
            )
        )
    )
)

exit /b
  • >> myupdate.txt echo(%%A writes each line.
  • >> myupdate.txt echo --- INSERT writes new line to insert.

If system memory permits based on file size, this is much faster:

@echo off
setlocal enabledelayedexpansion

set "i=0"
set "gfu="

(
    for /f "tokens=*" %%A in (myfile.txt) do (
        set /a i+=1
        set "line=%%~A"

        echo(%%A

        if "%%~A" == "QFU;" (
            set /a "qfu=!i! + 1"
        ) else if "!line:~,11!" == "LastUpdate=" (
            if defined qfu (
                if !i! gtr !qfu! (
                    echo --- INSERT
                    set "qfu="
                )
            )
        )
    )
) > myupdate.txt

exit /b

Used on 2.74 MB file, Time reduced from 70s to 21s. The write handle to myupdate.txt remains open for the entire loop, thus the write is cached.

Upvotes: 1

Related Questions