如何仅在两个模式都匹配时删除 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
让我们考虑这个简单的文件:
{
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