Reputation: 45
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
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