删除包含第一个匹配项的行以下 n 行之后的所有行

删除包含第一个匹配项的行以下 n 行之后的所有行

如果文件包含以下内容:

Line 1
FooLine 5
Line 2
Line 55
Line 3
Line 4
Line 5
Line 6
Line 7
Line 5
Line 8
Line 9

如何删除“第 5 行”之后两行以下的行,以便文件现在仅包含以下内容?

Line 1
FooLine 5
Line 2
Line 55
Line 3
Line 4
Line 5
Line 6
Line 7

注意:这是问题的稍微改进和颠倒的版本删除包含第一个匹配项的行上方 n 行之前的所有行

答案1

sed

$ sed '/^Line 5$/{n;n;q;}' file
Line 1
FooLine 5
Line 2
Line 55
Line 3
Line 4
Line 5
Line 6
Line 7

要就地编辑文件,请添加-iGNUsed或兼容版本或-i ''FreeBSDsed或兼容版本的选项。

答案2

使用任何 awk:

$ awk -v n=2 'c&&!--c{exit} $0 == "Line 5"{c=n+1} 1' file
Line 1
FooLine 5
Line 2
Line 55
Line 3
Line 4
Line 5
Line 6
Line 7

使用 sed-or-awk-a-line-following-a-matching-pattern 打印/17914105#17914105以获得解释和相关习语。

答案3

这里有几种方法,这两种方法都假设您想要开始删除只包含确切字符串的行之后的两行Line 5

  • 珀尔

    $ perl -lne '$k=$. if /^Line 5$/; print; exit if $k and $.==$k+2;' file
    Line 1
    FooLine 5
    Line 2
    Line 55
    Line 3
    Line 4
    Line 5
    Line 6
    Line 7
    

    您可以使用perl -i -lne '$k=$. if /^Line 5$/; print; exit if $k and $.==$k+2;' file它就地编辑文件。

  • awk

    awk '(/^Line 5$/){ k=NR } 1; (k && NR==k+2){exit};' file
    Line 1
    FooLine 5
    Line 2
    Line 55
    Line 3
    Line 4
    Line 5
    Line 6
    Line 7
    

答案4

使用(以前称为 Perl_6)

~$ raku -pe 'if m/^Line \h 5$/ {.put; get.put xx 2; last};'  file

或者:

~$ raku -pe 'm/^Line \h 5$/ && .put && get.put xx 2 && last;'  file 

或者:

~$ raku -ne 'm/^Line \h 5$/ ?? (.put; get.put xx 2; last) !! .put;'  file

以下是用 Raku(Perl 编程语言家族的成员)编写的答案。 Raku 具有对 Unicode 的内置高级支持。

在第一对答案中,-pe使用自动打印逐行标志。行将自动打印,直到读取所需的行(通过正则表达式确定)。此时所需的行已 out put,代码指示get另外两行并out放置它们,然后就是last(即代码退出)。请注意,对于这两个示例中的第二个,andthen可以使用 代替&&

在第三个答案中,-ne使用非自动打印逐行标志。每一行都被读入 Raku 的测试 ?? 真的 !! 错误的三元运算符通过正则表达式找到所需的行。如果所需的行为 True,则为 out put,代码指示get另外两行并将out它们放入,然后就是last(即代码退出)。如果通过正则表达式所需的行为 False,则它会直接输出put,并且继续逐行读取,可能会读到文件末尾。

输入示例:

Line 1
FooLine 5
Line 2
Line 55
Line 3
Line 4
Line 5
Line 6
Line 7
Line 5
Line 8
Line 9

示例输出:

Line 1
FooLine 5
Line 2
Line 55
Line 3
Line 4
Line 5
Line 6
Line 7

get.put注意:对于上述所有三个答案,空行可以很好地处理,但是如果您尝试返回不存在的行(例如,如果您太接近文件末尾),代码将引发错误。

为了更优雅地处理这个问题(返回匹配行之后可用的任何行,直到请求的数量),请使用以下与 @terdon 的 Perl 答案类似的代码。下面设置$k为等于“n+1“lines 返回当前行加上”n"-后面的行($k=3给出与上面相同的输出):

~$ raku -ne 'my $k=3 if m/^Line \h 5$/; $k.put && --$k; last unless $k;'  file

https://docs.raku.org
https://raku.org

相关内容