Solved Find a string and copy the lines before and after

October 2, 2012 at 09:06:48
Specs: Windows 7
I need a batch job that will read every line of a txt file. If the line contains some specific string, then I need it to copy that line and one line before and after it.

See More: Find a string and copy the lines before and after

Report •


✔ Best Answer
October 2, 2012 at 14:29:36
Using that as an input file this worked for me. I used -ERROR as my search string:

@echo off & setlocal enabledelayedexpansion
set #=0
set infile=test.txt
set str=-ERROR
for /f "tokens=1,* delims=:" %%a in (
'type %infile% ^| findstr /n /c:"%str%"'
) do (
set line2=%%b
set start=%%a
)
set /a start+=1
for /f "tokens=*" %%i in (
%infile%
) do (
set /a #+=1
if [!#!]==[%start%] (
set line3=%%i
))
set /a start-=2
set #=0
for /f "tokens=*" %%i in (
%infile%
) do (
set /a #+=1
if [!#!]==[%start%] (
set line1=%%i
))
>outfile.txt echo %line1%
>>outfile.txt echo %line2%
>>outfile.txt echo %line3%

Tony



#1
October 2, 2012 at 11:25:09
That's going to be a challenge but I will try and post back.

Tony


Report •

#2
October 2, 2012 at 12:30:34
This is ugly but it works.

@echo off & setlocal enabledelayedexpansion
set #=0
set infile=yourfile.txt
set str=Your string here
for /f "tokens=1,* delims=:" %%a in (
'type %infile% ^| findstr /n /c:"%str%"'
) do (
set line2=%%b
set start=%%a
)
set /a start+=1
for /f "tokens=*" %%i in (
%infile%
) do (
set /a #+=1
if [!#!]==[%start%] (
set line3=%%i
))
set /a start-=2
set #=0
for /f "tokens=*" %%i in (
%infile%
) do (
set /a #+=1
if [!#!]==[%start%] (
set line1=%%i
))
(
echo %line1%
echo %line2%
echo %line3%
)>outfile.txt

Tony


Report •

#3
October 2, 2012 at 13:32:49
It is grabbing the line numbers for all three lines but for lines 1 and 3 it only outputs "ECHO Off"

Report •

Related Solutions

#4
October 2, 2012 at 13:49:57
Post your input file.

Tony


Report •

#5
October 2, 2012 at 13:58:08
ECHO is off.
A decollate 3652/ 5180 09-29-2012 06:06:20 -ERROR : DSDDFP001E: Parser Syntax Error: AT LINE: 1 COL: 135133 FOUND: Des EXPECTED: Bundle, Archive, Set, Dest, DestGroup, Recp, Index, Name, User
ECHO is off.

Report •

#6
October 2, 2012 at 13:59:17
ECHO is off. are the first the third lines that appear in the output file.

Report •

#7
October 2, 2012 at 14:04:54
Here is a small portion of the file and ERROR is the line I want to grab along with the line before and after it.

A automate 3140/ 520 09-24-2012 09:51:09 -SYS : BMCDAP0600I Starting execution of D:\Oracle_IN\SHIPDA1.pdf with command line D:\CONTROL-D\CTD-bat-files\DECOLLATEORACLE.bat SHIPDA1.pdf "D:\Oracle_IN\SHIPDA1.pdf". Control/D/Automation Process directory is "ORACLE_IN".
A automate 3140/ 520 09-24-2012 09:51:09 -SYS : BMCDAP0604I The command that is passed to the system is: D:\CONTROL-D\CTD-bat-files\DECOLLATEORACLE.bat SHIPDA1.pdf "D:\Oracle_IN\SHIPDA1.pdf".
A decollate 4736/ 3172 09-24-2012 09:51:11 -SYS : Starting Decollation (Input file: D:\ORACLE_IN\SHIPDA1.pdf, Definition name: SHIPDA1).
A decollate 4736/ 3172 09-24-2012 09:51:11 -ERROR : DSDDFP001E: Parser Syntax Error: AT LINE: 1 COL: 135135 FOUND: N EXPECTED: Bundle, Archive, Set, Dest, DestGroup, Recp, Index, Name, User
A decollate 4736/ 3172 09-24-2012 09:51:11 -FATAL Decollator::Decollator : 46 DSDDFP009E: Syntax errors were detected
A automate 3140/ 520 09-24-2012 09:51:11 -SYS : BMCDAP0601I Execution of file D:\Oracle_IN\SHIPDA1.pdf successfully completed. Control/D/Automation Process directory is "ORACLE_IN".
A automate 3140/ 4676 09-24-2012 09:51:14 -SYS : BMCDAP0500I DONE Queue. size: 3.
A automate 3140/ 4676 09-24-2012 09:51:14 -SYS : BMCDAP0402I Moving D:\Oracle_IN\SHIPDA1.pdf to directory "done".
A automate 3140/ 4676 09-24-2012 09:51:14 -SYS : BMCDAP0404I D:\Oracle_IN\SHIPDA1.pdf was successfully moved to directory "done" as D:\Oracle_IN\done\SHIPDA1.pdf.
A automate 3140/ 4224 09-24-2012 09:51:22 -SYS : BMCDAP0500I WAITING Queue. size: 1.
A automate 3140/ 5072 09-24-2012 09:51:48 -SYS : BMCDAP0500I READY Queue. size: 1.


Report •

#8
October 2, 2012 at 14:29:36
✔ Best Answer
Using that as an input file this worked for me. I used -ERROR as my search string:

@echo off & setlocal enabledelayedexpansion
set #=0
set infile=test.txt
set str=-ERROR
for /f "tokens=1,* delims=:" %%a in (
'type %infile% ^| findstr /n /c:"%str%"'
) do (
set line2=%%b
set start=%%a
)
set /a start+=1
for /f "tokens=*" %%i in (
%infile%
) do (
set /a #+=1
if [!#!]==[%start%] (
set line3=%%i
))
set /a start-=2
set #=0
for /f "tokens=*" %%i in (
%infile%
) do (
set /a #+=1
if [!#!]==[%start%] (
set line1=%%i
))
>outfile.txt echo %line1%
>>outfile.txt echo %line2%
>>outfile.txt echo %line3%

Tony


Report •

#9
October 2, 2012 at 19:05:04
@Tony: same idea, just tried to streamline your code some. (findstr confuses me much of the time, but it IS better than find in most cases.)

@echo off>errors & setlocal enabledelayedexpansion
set log=logfile
set srch=-ERROR
for /f "tokens=1,2 delims=[]" %%a in ('find /n "%srch%"^<%log%') do call :xx %%a
goto :eof

:xx
set /a sk=%1-2
set c=0
>> errors echo --------------------------------------
for /f "tokens=* skip=%sk%" %%c in (%log%) do (
>> errors echo %%c
set /a c+=1
if !c! equ 3 goto :eof
)


Report •

#10
October 3, 2012 at 06:56:16
lol this was harder than i expected, i have no idea why it isn't working properly hopefully someone can figure the problem i haven't had much sleep either, anyway

@echo off & setlocal enabledelayedexpansion
type nul> lines.txt
set str=?
set /p str=Enter string to search for:
set Counter=1
for /f %%x in (source.txt) do (
set "Line_!counter!=%%x"
set /a counter+=1
)
set /a NumLines=Counter - 1
set reverse=0
set before=0
:LOOP
set reverse=%before%
if "%reverse%"=="%counter%" exit
set /A reverse +=1
set before=%reverse%
echo !Line_%reverse%! | find "%str%" > nul 2>&1
if not errorlevel 1 (
echo.!Line_%reverse%!>> lines.txt
set /A reverse -=1
if "%reverse%" NEQ "0" echo.!Line_%reverse%!>> lines.txt
set /A reverse +=2
echo.!Line_%reverse%!>> lines.txt
)
Goto :LOOP


Report •

#11
October 3, 2012 at 08:23:57
I have tried both and it refuses to grab the outer lines. If it is at least getting the line numbers of all 3 lines, is there a way to extract the lines by line number. I tried using awk, but on windows it errors " 'awk' is not recognized as an internal ..." bla bla bla.

Report •

#12
October 3, 2012 at 10:31:17
Then there must be some difference between the sample you posted and the actual log you're trying to parse. Maybe post the entire log to pastebin.com.

Tony


Report •

#13
October 3, 2012 at 16:33:55
might try posting your data with a "pre" tag preceding it. (substitutes lss for [ and gtr for ] in foll. example:)
[pre]
data
data
[/pre]

it may be a line-feed/car.ret problem, although i doubt it. My test worked with your data as given...

You might try this script, just as a test:
::==== begin script
@echo off & setlocal enabledelayedexpansion
set log=logfile
set srch=-ERROR
for /f "tokens=1,2 delims=[]" %%a in ('find /n "%srch%"^<%log%') do call :xx %%a
goto :eof

:xx
set /a sk=%1-2
more +%sk% %log%
::===== end script

and see if "more" can pick up that first line where "for" could not. doubtful

last resort: use find or findstr to number each line, then use findstr to look for the target line numbers at beginning of the lines:

::==== begin script
@echo off & setlocal enabledelayedexpansion
set log=logfile
set srch=-ERROR
for /f "tokens=1,2 delims=[]" %%a in ('find /n "%srch%"^<%log%') do call :xx %%a
goto :eof

:xx
set /a sk=%1-2
set /a ks=sk+2
find /n /v ""<%log% | findstr /r "^\[[%sk%-%ks%"
::===== end script


Report •

#14
October 9, 2012 at 12:03:00
Dont know why but I think its finally working now. Thanks alot for your help. I will be able to use this on other error logs and create reports.

Thanks again


Report •


Ask Question