Regex sed-从模式2之前的模式1删除到模式2之后的模式3

Regex sed-从模式2之前的模式1删除到模式2之后的模式3,regex,awk,sed,multiline,Regex,Awk,Sed,Multiline,如果在两个模式之间发现另一个模式,我会尝试删除两个模式之间的线条,包括带有模式本身的线条,但我不确定如何处理它 假设我有如下输入,并希望删除第6行到第11行,因为模式notthis位于模式start和end之间: start AHBUe3Ar5NoD 3EcuCcD2QCja 7VmlKFbD8Rbi end start OgytsRhZbD8T notthis 0PlcUh2RLvVW tsz2S80SyW9p end start dQ5qiZCvBqcK SufdS40X1Sh2 B1cyN

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

假设我有如下输入,并希望删除第6行到第11行,因为模式
notthis
位于模式
start
end
之间:

start
AHBUe3Ar5NoD
3EcuCcD2QCja
7VmlKFbD8Rbi
end
start
OgytsRhZbD8T
notthis
0PlcUh2RLvVW
tsz2S80SyW9p
end
start
dQ5qiZCvBqcK
SufdS40X1Sh2
B1cyNshOj2Z4
end
我把我认为我理解的东西改成了这样的东西,但它不起作用:

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

是否因为
N
只将初始模式
^start$
后面的行附加到模式空间,而忽略后面的内容?那么,实现我想要的目标的正确方法是什么呢?

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 $0 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都能高效、可靠地工作,并且易于理解,并且在您的需求发生变化时进行修改。

下面是另一个
awk
脚本。希望匹配部分问题描述

script.awk

BEGIN {omitMark = "notthis"}  # assign omit marker as ReqExp
/start/, /end/ {   # define RegExp range for omission section 
    if ($0 ~ 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):


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

希望在编写一个包含符文的脚本时会出现这样的情况,比如
/^start$/{$!{N;/^start\N(.\N)*notthis.\N(.\N)*end/d;ty;p;d;:y}
当你想一想——“我在干什么?”!谢谢你,很有魅力。请您解释一下这两种方法好吗?第一种方法每次读取一整条记录(多行文本块),其中每条记录以
end\n
结尾,如果不包含
notthis
,则打印该记录。第二个在找到
start
时设置一个标志,在设置该标志时一次建立一行记录,然后在找到
end
时,如果记录不包含
notthis
,则打印该记录。在浏览awk手册页后,如果您对语法有任何具体问题,请告诉我。如果您考虑使用范围表达式,请确保理解上的讨论。
sed '/^start/{:a;N;/end$/!ba;/notthis/d}' file