grep for a particular pattern and remove 5 lines above the pattern and 6 lines below the pattern
root@server1 [~]# cat filename
Shell Programming and Scripting test1
Shell Programminsada asda
dasd asd Shell Programming and Scripting Post New Thread
Shell Programming and S sadsa sadcripting Post New Thread
Shell Progsdaas dsadsaramming and Scripting Post New Thread
Shell Programming and Scripting Post New Thread
Shell Programming and Scripting Post New Thread
Shell Programming and Scripting Post New Thread
Shell Programming and Scripting Post New Thread
Shell Programming and Scripting Post New Thread
pattern_to_remove
Shell Programming and Scripting Post New Thread
Shell Programming awetrtg teyy teyer nd Scripting Post New Thread
Shell Programming and Scripting Post New Thread
Shell Programming and Scripting Post New Thread
Shell Programming and rewrwt r t Scripting Post New Thread
Shell Programming and Scripting Post New Thread
Shell Programmingsadas ade and Scripting Post New Thread
Shell Programming and Scripting Post New Thread
Shell Programming and Scripting Post New Thread
Shell Programminsadsa asdad`g and Scripting Post New Thread
Prefix each line of output with the line number within its input file.
#######################################################################################
Have a look for a utility called vmsgrep. I've got the source code if you need it. It does exactly what you are asking to do (pull out a specified number of lines above/below your pattern match).
It could be done with nawk.
2 ways: getting a line numbers and skip line between; or
keep all the time last 6 (in your case) lines, and print 7-th back line.
Here is 1-st way solution:
# prepare file for testing:
n=0; fl=for_removing_lines.txt; rmv_lbl="point of removing"; rm $fl;
while [ $n -le 20 ];do
(( n++ )); echo "line $n">>$fl;
if [ $n -eq 10 ]; then
echo $rmv_lbl>>$fl;
fi;
done;
# geting line numbers to statr and END remuving
pnt_ln=`nawk -v srch="$rmv_lbl" '{if($0~srch) print NR; }' $fl`;
((rmv_st=pnt_ln-6));
((rmv_end=pnt_ln+6)); echo $pnt_ln, $rmv_st, $rmv_end
# printing file without 6 lines before and after label line
nawk -v st=$rmv_st -v end=$rmv_end '{if( (NR <= st)||(NR >= end) ) print $0; }' $fl
Using an older tool, the programmable interactive line editor ed or ex:
#!/usr/bin/env sh
# @(#) s3 Demonstrate deleting a range with line editor.
# ____
# /
# | Infrastructure BEGIN
echo
set -o nounset
debug=":"
debug="echo"
## The shebang using "env" line is designed for portability. For
# higher security, use:
#
# #!/bin/sh -
## Use local command version for the commands in this demonstration.
EDITOR=ex
EDITOR=ed
set +o nounset
echo "(Versions displayed with local utility \"version\")"
version >/dev/null 2>&1 && version =o $(_eat $0 $1) $EDITOR
set -o nounset
echo
FILE=data1
cp sacred $FILE
echo " Input file $FILE:"
cat $FILE
before=5
after=6
pattern="pattern"
# | Infrastructure END
# \
# ---
echo
echo " Output from editor $EDITOR:"
$EDITOR <<EOF $FILE
/$pattern/-${before},/$pattern/+${after}d
w
q
EOF
echo
echo " Output file $FILE:"
cat $FILE
exit 0
Producing:
% ./s3
(Versions displayed with local utility "version")
Linux 2.6.11-x1
GNU bash, version 2.05b.0(1)-release (i386-pc-linux-gnu)
GNU ed version 0.2
Input file data1:
-10
-9
-8
-7
-6
-5
-4
-3
-2
-1
pattern
1
2
3
4
5
6
7
8
9
10
Output from editor ed:
60
25
Output file data1:
-10
-9
-8
-7
-6
7
8
9
10
I like this approach for small jobs because the syntax of the range is so understandable -- from the pattern so many lines back, to the pattern plus so many lines forward.
A disadvantage is that this can be slow on large files because the entire file is read.
Ok, what you want is to delete 10 lines before and 9 lines after the pattern including the line of the pattern.
With my solution the file must be insert 2 times on the last line:
If what you really actually want is for anything between two occurrences of ?> matching your pattern to be removed, rather than static numbers of lines of text, perhaps something like this would work.