sed - 从 pattern2 之前的 pattern1 删除到 pattern2 之后的 pattern3

sed - delete from pattern1 before pattern2 to pattern3 after pattern2

我正在尝试删除两个模式之间的线条,包括带有模式本身的线条,如果在它们之间发现另一个模式,但我不确定如何解决它。

假设我有一个如下所示的输入并且想要删除第 6 行到第 11 行,因为在模式 startend 之间找到了模式 notthis:

start
AHBUe3Ar5NoD
3EcuCcD2QCja
7VmlKFbD8Rbi
end
start
OgytsRhZbD8T
notthis
0PlcUh2RLvVW
tsz2S80SyW9p
end
start
dQ5qiZCvBqcK
SufdS40X1Sh2
B1cyNshOj2Z4
end

我将我认为我理解的内容从 this answer 更改为类似这样的内容,但它不起作用:

/^start$/{$!{N;/^start\n(.*\n)*notthis.*\n(.*\n)*end/d;ty;P;D;:y}}

是否因为 N 仅将初始模式 ^start$ 之后的行附加到模式 space 而忽略了后面的内容?实现我想要的目标的正确方法是什么?

sed 用于对单个字符串进行简单替换,就是全部。对于其他任何你应该使用 awk,例如使用 GNU awk for mult-char RS 这个简短的脚本将从你发布的输入中产生你想要的输出:

$ awk 'BEGIN{RS=ORS="end\n"} !/notthis/' file
start
AHBUe3Ar5NoD
3EcuCcD2QCja
7VmlKFbD8Rbi
end
start
dQ5qiZCvBqcK
SufdS40X1Sh2
B1cyNshOj2Z4
end

或使用任何 awk 更清晰、更健壮、更容易增强:

$ cat tst.awk
/start/ { f = 1 }
f {
    rec = rec [=11=] ORS
    if ( /end/ ) {
        if ( rec !~ /notthis/ ) {
            printf "%s", rec
        }
        rec = ""
        f = 0
    }
}
$
$ awk -f tst.awk file
start
AHBUe3Ar5NoD
3EcuCcD2QCja
7VmlKFbD8Rbi
end
start
dQ5qiZCvBqcK
SufdS40X1Sh2
B1cyNshOj2Z4
end

在每个 UNIX 机器上使用任何 shell 中的任何 awk,上面的代码将有效且稳健地工作,易于理解并且修改起来很简单 if/when 您的需求更改。

这是另一个 awk 脚本。希望与部分问题描述相符。

script.awk

BEGIN {omitMark = "notthis"}  # assign omit marker as ReqExp
/start/, /end/ {   # define RegExp range for omission section 
    if ([=10=] ~ omitMark) next;  # if matched omission marker skip processing
    print;  # print not ommited currnt line in section
    next;   # skip to process next line in section
}
1;  # print any line not in section.

input.txt

start
AHBUe3Ar5NoD
3EcuCcD2QCja
7VmlKFbD8Rbi
end
start
OgytsRhZbD8T
notthis
0PlcUh2RLvVW
tsz2S80SyW9p
end
notthis
start
dQ5qiZCvBqcK
SufdS40X1Sh2
B1cyNshOj2Z4
notthis
end
notthis

运行:

awk -f script.awk input.txt

输出:

start
AHBUe3Ar5NoD
3EcuCcD2QCja
7VmlKFbD8Rbi
end
start
OgytsRhZbD8T
0PlcUh2RLvVW
tsz2S80SyW9p
end
notthis
start
dQ5qiZCvBqcK
SufdS40X1Sh2
B1cyNshOj2Z4
end
notthis

这可能适合您 (GNU sed):

sed '/^start/{:a;N;/end$/!ba;/notthis/d}' file

收集 startend 之间的行,如果它们包含字符串 notthis 则删除它们。