我会试一试。
删除模式后的 5 行(包括带有模式的行):
sed -e '/pattern/,+5d' file.txt
删除模式后的 5 行(不包括有模式的行):
sed -e '/pattern/{n;N;N;N;N;d}' file.txt
/pattern/,+5
定义了一个范围,该范围以包含“模式”的行 (/pattern/
) 开始,并在 5 行之后结束 (+5
)。最后一个字符 d
是在该范围内的每一行上运行的命令,即“删除”。在第二个配方中,它不是匹配范围,而是仅匹配包含模式 (/pattern/
) 的行,然后运行一系列命令:{n;N;N;N;N;d}
,它基本上打印下一行 (n
),然后读取并最终丢弃接下来的 4 行 (N;N;N;N;d
)。
sed -e '/pattern/{n;N;N;N;N;d;}' file.txt
something
执行:sed -E '/^something$/,$d'
,其中 -E
是 POSIX 可移植性扩展正则表达式。
没有 GNU 扩展(例如在 macOS 上):
删除图案后的 5 行(包括带图案的线)
sed -e '/pattern/{N;N;N;N;d;}' file.txt
添加 -i ''
以就地编辑。
简单的awk
解决方案:
假设用于查找匹配行的正则表达式存储在 shell 变量 $regex
中,要跳过的行数存储在 $count
中。
如果应该也跳过匹配的行(跳过$count + 1
行):
... | awk -v regex="$regex" -v count="$count" \
'$0 ~ regex { skip=count; next } --skip >= 0 { next } 1'
如果应该不跳过匹配行(跳过匹配之后的$count
行):
... | awk -v regex="$regex" -v count="$count" \
'$0 ~ regex { skip=count; print; next } --skip >= 0 { next } 1'
解释:
-v regex="$regex" -v count="$count" 根据同名的 shell 变量定义 awk 变量。
$0 ~ 正则表达式匹配感兴趣的行 { skip=count; next } 初始化跳过计数并继续到下一行,有效地跳过匹配行;在第二个解决方案中,下一个之前的打印确保它不会被跳过。 --skip >= 0 减少跳过计数,如果它(仍然)>= 0 则采取行动,这意味着应该跳过手头的行。 { next } 进入下一行,有效地跳过当前行
{跳过=计数; next } 初始化跳过计数并继续到下一行,有效地跳过匹配行;在第二个解决方案中,下一个之前的打印确保它不会被跳过。
--skip >= 0 减少跳过计数,如果它(仍然)>= 0 则采取行动,这意味着应该跳过手头的行。
{ next } 进入下一行,有效地跳过当前行
是 { print } 的常用简写;也就是说,当前行只是简单地打印只有非匹配和非跳过的行到达这个命令。 1 等价于 { print } 的原因是 1 被解释为布尔模式,根据定义,该模式始终评估为 true,这意味着其关联的操作(块)是无条件执行的。由于在这种情况下没有关联的操作,awk 默认打印该行。
只有不匹配和未跳过的行到达此命令。
1 等价于 { print } 的原因是 1 被解释为布尔模式,根据定义,该模式始终评估为 true,这意味着其关联的操作(块)是无条件执行的。由于在这种情况下没有关联的操作,awk 默认打印该行。
这可能对您有用:
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
pattern_number.txt
是一个 2 列文件,其中包含要在第一列中匹配的模式,在第二列中包含要跳过的行数。第一个 sed
命令将文件转换为执行相应匹配和跳过的 sed
脚本;该脚本通过 -f
和 stdin (-
) 提供给第二个 sed
命令。第二个 sed
命令对由 seq 21
的输出形成的示例 ad-hoc 输入文件进行操作,以证明它可以工作。
使用 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
$
此解决方案允许您将“n”作为参数传递,它将从文件中读取您的模式:
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 -
名为“-”的文件表示 awk 的标准输入,因此适用于您的管道
+N
模式是 GNU 扩展。在第二个示例中将第一个n
更改为N
以使其包含带有模式的行。