sed or awk: delete n lines following a pattern
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
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
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"
definesawk
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, theprint
beforenext
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 line
1
is a commonly used shorthand for{ print }
; that is, the current line is simply printed- Only non-matching and non-skipped lines reach this command.
- The reason that
1
is equivalent to{ print }
is that1
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.