如何使用sed删除匹配的行,上面的行和下面的行?

时间:2009-05-18 06:19:15

标签: regex sed

我在文件中多次出现以下序列:

yyyy
xxxx
zzzz

我有一个匹配xxxx的正则表达式。每当匹配时,我想删除该行,之前的行(例如yyyy)和之后的行(例如zzzz)。我如何使用sed来做到这一点?

7 个答案:

答案 0 :(得分:13)

诀窍是存储“保留空间”中的最后一行。

sed -n '
/^xxxx/{n
        n
        x
        d
       }
x
1d
p
${x
  p
 }
' <input file>

x开始 - 将当前输入行与保留空间(x)交换,然后第一行不打印任何内容(1d),后续行打印刚从保持空间(p)交换的线,在最后一行再次交换保留空间并打印其中的内容($x{x p}。这样,当我们到达目标线时该做什么(从/^xxxx/开始 - 将下两行读入模式空间(n n)并将模式空间与保持空间(x)交换 - 这会留下下一行的保留空间想要在比赛前用线打印和模式空间,这是我们不想要的,所以我们抛弃它(d

答案 1 :(得分:1)

您可以查看this document。它涵盖了使用sed处理多行。

答案 2 :(得分:0)

这就是我在perl中的表现,也许它可以帮助你找到正确的轨道......祝你好运!

open(INFILE,"<in.txt");
my(@arrayOutBoundData, $skipNextLine)l
for (<INFILE>) {
    if (not $skipNextLine) {
        if (/^xxxx$/) {
            pop(@arrayOutBoundData);
            $skipNextLine = 1;
        } else {
            push(@arrayOutBoundData,$_);
        }
    }
$skipNextLine = 0
}

open(OUTFILE,">out.txt");
for (@arrayOutBoundData) {
    print OUTFILE;
}

(未在此系统上测试过没有perl请原谅任何现场。)

答案 3 :(得分:0)

这可能适合你(GNU sed):

echo -e "a\nyyyy\nxxxx\nzzzz\nb" | sed 'N;/^xxxx/M{/^xxxx/d;$!N;d};P;D'
a
b

这会在模式空间中保留两行窗口,如果在第一行或第二行中找到所需的正则表达式,则读取以下行,然后删除所有三行。边缘情况是在前/后没有行的情况下在第一行或最后一行中找到正则表达式。在这些情况下,只能删除两行。

顺便提一下,这个解决方案可能在GNU sed中发现了一个可能的错误。地址的M标志允许将^$元字符用作多行字符串中行的起点和终点的正则表达式中的零长度标记。空地址//重复使用先前声明的地址。该地址应该是包含多行标志的地址吗?目前它似乎包括国旗,即使没有说明,即

sed 'N;/^xxxx/M{/^xxxx/d;$!N;d};P;D' file

产生不同的(正确的)结果:

sed 'N;/^xxxx/M{//d;$!N;d};P;D' file

如果xxxx出现在文件的第二行。

答案 4 :(得分:0)

您可以使用以下内容:

sed -n '/xxxx/{N;s/.*//;x;d;};x;p;${x;p;}'

这将用一个空行代替3行。

答案 5 :(得分:0)

您可以先撤消该文件,使用sed删除匹配的行和下一行(或+Nd命令中的行sed),最后反转结果:

tac old.file | sed -e '/xxxx/,+1d' | tac > new.file

答案 6 :(得分:-1)

grep -v -f <(grep -1 "xxxx" file) file