我正在尝试删除两个模式之间的线,包括带有模式本身的线,如果在它们之间找到了另一个模式,但是我不确定如何解决。
说我有类似以下内容的输入,并想删除#6至#11行,因为在模式notthis
和start
之间找到了模式end
:
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$
之后的行追加到模式空间,而忽略了随后的内容吗?而实现我想要达到的目标的正确方法是什么?
答案 0 :(得分:3)
sed用于单个字符串全部上的简单替换。对于其他任何事情,您都应该使用awk,例如对于Gult awk,使用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高效,可靠地工作,易于理解,并且在需求更改时易于修改。
答案 1 :(得分:0)
这是另一个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
答案 2 :(得分:0)
这可能对您有用(GNU sed):
sed '/^start/{:a;N;/end$/!ba;/notthis/d}' file
收集start
和end
之间的行,如果它们包含字符串notthis
,则将其删除。