To begin with, if you want to delete a line containing the keyword, you would run sed as shown below. Similarly, you could run the sed command with option -n and negated p , (! p) command. To delete lines containing multiple keywords, for example to delete lines with the keyword green or lines with keyword violet.
To delete a line, we'll use the sed “d” command. Note that you have to declare which line to delete. Otherwise, sed will delete all the lines.
The sed command can remove the lines of any range. For this, we just have to enter 'minimum' and 'maximum' line numbers. In this example, we will remove the lines ranging from 4 to 7 numbers. After removing these ranges of lines, our file will look like this.
Deleting Multiple LinesPress the Esc key to go to normal mode. Place the cursor on the first line you want to delete. Type 5dd and hit Enter to delete the next five lines.
I'll have a go at this.
To delete 5 lines after a pattern (including the line with the pattern):
sed -e '/pattern/,+5d' file.txt
To delete 5 lines after a pattern (excluding the line with the pattern):
sed -e '/pattern/{n;N;N;N;N;d}' file.txt
Without GNU extensions (e.g. on macOS):
To delete 5 lines after a pattern (including the line with the pattern)
sed -e '/pattern/{N;N;N;N;d;}' file.txt
Add -i ''
to edit in-place.
Simple awk
solutions:
Assume that the regular expression to use for finding matching lines is stored in shell variable $regex
, and the count of lines to skip in $count
.
If the matching line should also be skipped ($count + 1
lines are skipped):
... | awk -v regex="$regex" -v count="$count" \
'$0 ~ regex { skip=count; next } --skip >= 0 { next } 1'
If the matching line should not be skipped ($count
lines after the match are skipped):
... | awk -v regex="$regex" -v count="$count" \
'$0 ~ regex { skip=count; print; next } --skip >= 0 { next } 1'
Explanation:
-v regex="$regex" -v count="$count"
defines awk
variables based on shell variables of the same name.$0 ~ regex
matches the line of interest
{ skip=count; next }
initializes the skip count and proceeds to the next line, effectively skipping the matching line; in the 2nd solution, the print
before next
ensures that it is not skipped.--skip >= 0
decrements the skip count and takes action if it is (still) >= 0, implying that the line at hand should be skipped.{ next }
proceeds to the next line, effectively skipping the current line1
is a commonly used shorthand for { print }
; that is, the current line is simply printed
1
is equivalent to { print }
is that 1
is interpreted as a Boolean pattern that by definition always evaluates to true, which means that its associated action (block) is unconditionally executed. Since there is no associated action in this case, awk
defaults to printing the line.This might work for you:
cat <<! >pattern_number.txt
> 5 3
> 10 1
> 15 5
> !
sed 's|\(\S*\) \(\S*\)|/\1/,+\2{//!d}|' pattern_number.txt |
sed -f - <(seq 21)
1
2
3
4
5
9
10
12
13
14
15
21
Using Perl
$ cat delete_5lines.txt
1
2
3
4
5 hello
6
7
8
9
10
11 hai
$ perl -ne ' BEGIN{$y=1} $y=$. if /hello/ ; print if $y==1 or $.-$y > 5 ' delete_5lines.txt
1
2
3
4
11 hai
$
This solution allows you to pass "n" as a parameter and it will read your patterns from a file:
awk -v n=5 '
NR == FNR {pattern[$0]; next}
{
for (patt in pattern) {
if ($0 ~ patt) {
print # remove if you want to exclude a matched line
for (i=0; i<n; i++) getline
next
}
}
print
}
' file.with.patterns -
The file named "-" means stdin for awk, so this is suitable for your pipeline
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With