Here is a very simple solution that works well with small files.
Code: Select all
@echo off
setlocal enableDelayedExpansion
set "word=WORD"
set "keep=3"
set "file=test.txt"
set n=%keep%
for /f "usebackq delims=" %%A in ("%file%") do (
set "ln=%%A"
if "!ln:%word%=!" neq "!ln!" (
echo(
set n=0
)
if !n! lss !keep! (
echo !ln!
set /a n+=1
)
)
But the above code has the following limitations:
- Blank lines are ignored
- Lines beginning with ; are ignored
- Lines containing ! are corrupted
- The search is case insensitive
- The WORD cannot contain = or !
- The WORD cannot start with * or ~
- Lines must be less than ~8191 bytes long
- It is slow if the WORD appears infrequently within a large file
Nearly all of the problems can be fixed with various tweaks, but the basic strategy will always be slow with large files.
Here is a robust solution that overall gives good performance regardless the size of the file. The only remaining limitation is that lines must be less than ~8191 bytes long. (The line size limit decreases gradually as the number of lines increases because of the line number prefix that is added to each line)
Code: Select all
@echo off
setlocal disableDelayedExpansion
set "word=WORD"
set "keep=2"
set "file=test.txt"
set "tempBase=%temp%\search%random%"
setlocal enableDelayedExpansion
>"%tempBase%search" echo !word:\=\\!
>"%tempBase%keepers" (
for /f "delims=:" %%A in ('findstr /ng:"%tempBase%search" "%file%"') do (
for /l %%N in (0 1 %keep%) do (
set /a "N=%%A+%%N"
echo !N!:
)
)
)
endlocal
>"%tempBase%source" findstr /n "^" "%file%"
>"%tempBase%result" findstr /blg:"%tempBase%keepers" "%tempBase%source"
for /f "usebackq delims=" %%A in ("%tempBase%result") do (
set "ln=%%A"
setlocal enableDelayedExpansion
echo !ln:*:=!|findstr /g:"%tempBase%search" >nul && echo(
echo(!ln:*:=!
endlocal
)
del "%tempbase%*"
The code is significantly faster if the blank line is not required before each line that contains WORD. The last line that contains FINDSTR can be romoved if the blank lines are not required.
Dave Benham