删除文件中第 n 行(与模式匹配)之前的 x 行和之后的 y 行

删除文件中第 n 行(与模式匹配)之前的 x 行和之后的 y 行

如果第二行与正则表达式 N+ 匹配,我试图从文本文件中删除四行块。文本文件由许多重复的4行格式组成,即:

@HEADER1
ACTGCNNNT
+
583@#!NMY
@HEADER2
ANNTGCGGG
+
4123N@!&*

四块模式的第一行始终以 @ 开头,但是 @ 也可以出现在第四行的任何位置,并且由于我正在寻找的模式,N+ 也可以出现在第四行,我不能简单地grep 表示 N+。

任何想法将不胜感激:)

答案1

sed -ne:n -e's/\n/&/3;tp'  \
          -e'$!{N;bn' -e\} \
     -e:p -e'/\n.*N.*\n/p' \
<in >out

如果您的输入出现在每四行的常规块中,并且您正在寻找至少一个N发生在这四个中的最后一个,那么上面的内容sed应该可以满足您的需求。它确实假设您的整个输入文件将被分成四行组。如果情况并非如此,请告诉我,我可以让它不那么自以为是。

无论如何,首先sed收集 4 个输入行 - 或者拉入输入行,直到\n在模式空间中找到 3 个 ewline 分隔符 - 接下来它会查找N这不会发生在刚刚收集的 4 行中的第一行或最后一行上。如果找到,它p会打印四行组,否则不打印任何内容,下一个周期将从下一个四行组开始。

但显然,你正在尝试消除有问题的块。在这种情况下:

sed -e'$!N;/\n.*N/{$!N;$!N;d' -e'};n;n' <in >out

...会成功的。它首先将Next 输入行附加到模式空间,然后检查是否有N它发生在 4 行块的第二行,如果找到,则在删除整个块之前,在不是最后一行sed的任何行上再拉入两行。如果第二行!$d没有匹配N,它用 ext 输入行覆盖模式空间两次n- 自动打印 - 并自动打印最后一个。

当然,您也可以使用sedand just do 的第一位/\n.*N.*\n/!p来代替最后一个地址。p这可能是有利的,因为您可以通过将3每个块的行数切换为您可能感兴趣的任何其他行数来更轻松地更改它。

答案2

Perl 来救援!

另存为remove-blocks.pl,运行为perl remove-blocks.pl input_file > output_file

#!/usr/bin/perl
use strict;
use warnings;

my @four_lines;                      # Buffer to hold a block.
while (<>) {                         # Read the input line by line.
    if (@four_lines < 3) {           # Not reading the last line?
        push @four_lines, $_;        # Save it to the buffer.

    } else {
        print @four_lines, $_ if $four_lines[1] !~ /N+/;
        undef @four_lines;           # Clear the buffer.
    }
}

相关内容