如何仅在两个模式都匹配时删除 2 个连续的行

How to delete 2 consecutive lines only when both patterns are matched

让我们考虑这个简单的文件:

{
bla bla
bla bla bla
}
{
bla bla
bla bla bla
}
bla bla
bla bla bla

我只需要删除那些连续的行:

}
{

结果应该是:

{
bla bla
bla bla bla
bla bla
bla bla bla
}
bla bla
bla bla bla

我尝试了以下方法:

sed -e '/^}$/,/^{$/d' file

很遗憾,最后一个右花括号和剩余的行已被删除:

{
bla bla
bla bla bla
bla bla
bla bla bla

有什么建议吗?

如果需要,我愿意接受涉及其他工具的任何简单解决方案,例如 awk/perl/...。

Perl 解决方案:

perl -lne 'undef $prev, next if $prev eq "}" && $_ eq "{";
           print $prev if defined $prev;
           $prev = $_;
           END { print $prev if defined $prev}' -- file
  • -n 逐行读取输入并运行每一行的代码。
  • -l 从输入中删除换行符并将它们添加到 print.
  • 我们将上一行存储在$prev中。如果上一行是 } 而当前行是 {,我们忘记上一行并读取下一行。否则,我们打印前一行 如果有任何 (这意味着我们不会在忘记的行之后打印空行)。然后我们将当前行存储到 $prev 并重复。
  • 需要 END 部分来打印最后记住的行,如果有的话。

您可以使用这个 sed:

sed '/^}$/ { N; /\n{$/ d; }' file

{
bla bla
bla bla bla
bla bla
bla bla bla
}
bla bla
bla bla bla

要内联保存更改:

sed -i.bak '/^}$/ { N; /\n{$/ d; }' file

或者这个 awk 也可以工作:

awk '/^}$/ {p = [=12=]; next} p != "" {if (/^{$/) {p=""; next} [=12=] = p ORS [=12=]; p = ""} 1' file

{
bla bla
bla bla bla
bla bla
bla bla bla
}
bla bla
bla bla bla
$ sed '$!N;/^}\n{$/d;P;D' file
{
bla bla
bla bla bla
bla bla
bla bla bla
}
bla bla
bla bla bla

这两行缓冲区也适用于其他输入,如下面的测试所示:

$ cat test
}
}
{
foo
}
$ sed '$!N;/^}\n{$/d;P;D' test
}
foo
}

使用 GNU sed -z:

$ sed -z 's/}\n{\n//' file
{
bla bla
bla bla bla
bla bla
bla bla bla
}
bla bla
bla bla bla

使用 GNU awk 进行多字符 RS:

$ awk -v RS='}\n{\n' -v ORS= '1' file
{
bla bla
bla bla bla
bla bla
bla bla bla
}
bla bla
bla bla bla

你也可以使用这个 awk:

awk 'BEGIN{RS="";FS=OFS="\n"}{print ,,,,,,,}' file
{
bla bla
bla bla bla
bla bla
bla bla bla
}
bla bla
bla bla bla

或使用for循环:


awk 'BEGIN{RS="";FS=OFS="\n"}{
        for(i=1;i<=NF;i++) {
                if(i == 4 || i == 5) continue; print $i}
}' file
{
bla bla
bla bla bla
bla bla
bla bla bla
}
bla bla
bla bla bla