Regex 将多行模式非贪婪匹配到sed?

Regex 将多行模式非贪婪匹配到sed?,regex,sed,multiline,Regex,Sed,Multiline,填充: 我想打印所有块,如:[开始]。。。[停止]命令 结果应该是: [start] cmd1 afadfadf dafdf [ok] cmd1 [-] cmd2 [-] cmd3 [start] cmd4 dfdafadf d afasdf daf [stop] cmd4 [-] cmd5 [-] cmd6 [start] cmd1 adfadd dafa dfdd33r55ae [ok] cmd1 [-] cmd7 [start] cmd8 error... [stop] cmd8 [-

填充:

我想打印所有块,如:[开始]。。。[停止]命令

结果应该是:

[start] cmd1
afadfadf
dafdf
[ok] cmd1
[-] cmd2
[-] cmd3
[start] cmd4
dfdafadf
d
afasdf

daf
[stop] cmd4
[-] cmd5
[-] cmd6
[start] cmd1
adfadd
dafa
dfdd33r55ae
[ok] cmd1
[-] cmd7
[start] cmd8
error...

[stop] cmd8
[-] cmd9
[start] cmd10
exit xx

[stop] cmd10
[-] cmd
[start] cmd1
[ok] cmd1
我怎样才能用sed做到这一点

sed-n'/\[start\]/I、/\[stop\]/ip'
将不工作,因为range操作符在找到下一个[stop]之前不会停止

编辑: 使用@jaybee sed脚本后,我发现当[stop]行多于start行时,仍然存在一些问题,例如:

填充物2

[start] cmd4
dfdafadf
d
afasdf

daf
[stop] cmd4
[start] cmd8
error...

[stop] cmd8
[start] cmd10
exit xx

[stop] cmd10
它仍然会输出额外的[停止]行,如下所示:

[start] cmd1
afadfadf
dafdf
[ok] cmd1
[-] cmd2
[-] cmd3
[start] cmd4
dfdafadf
d
afasdf

daf
[stop] cmd4
[-] cmd5
[-] cmd6
[start] cmd1
adfadd
dafa
dfdd33r55ae
[ok] cmd1
[-] cmd7
[start] cmd8
error...

[stop] cmd8
[-] cmd9
[stop] sum
[stop] cmd1
[stop] cmd2
[start] cmd10
exit xx

[stop] cmd10
[-] cmd
[start] cmd1
[ok] cmd1
因此,我决定修改sedsrc以解决此问题:

[start] cmd4
dfdafadf
d
afasdf

daf
[stop] cmd4
[start] cmd8
error...

[stop] cmd8
[stop] cmd8
[-] cmd9
[stop] sum
[stop] sum
[stop] cmd1
[stop] cmd2
[stop] cmd2
[start] cmd10
exit xx

[stop] cmd10

现在它工作正常了,欢迎以后讨论如何使脚本更简洁。

好的,所以我建议您使用保留缓冲区,在看到新的
[start]
时刷新它,并在看到
[stop]
时打印它。这将生成以下脚本:

#n
/^\[start\]/I {h;d}
#if match [start] create a new hold buffer then delete the pattern space
/^\[stop\]/I {
#if match [stop] do this
H;x
#append line into hold buffer and then swap the hold buffer to pattern space
/^\[start\]/I{p;d}
#if the buffer contain [start], then it is a complete [start]...[stop] block, print the block,start over with next line
d
#if does not contain [start],start over with next line
}
/^\[.+\]/ {
#if it is other control word, do this
h;d
# clear and put current line to hold buffer, start over with next line
}

H
#append non-control line into hold buffer
您将其放入例如
sedscr
中,然后运行它以获得以下结果:

#n
/^\[start\]/I {
    h;n
}
/^\[stop\]/I {
    H;x;p;n
}
H
解释 看到该行开头的
[start]
(使用
I
标志,因为它似乎不区分大小写),将该行放入保留空间,擦除其以前的内容(
h
),然后输入下一行(
n

当看到
[stop]
时,将该行附加到保留空间(
H
),然后交换图案空间和保留空间(
x
)以打印图案空间(
p
),然后输入下一行(
n

在所有其他行上,只需将该行附加到当前保留空间(
H


顺便说一下,我脚本开头的
#n
相当于命令行上的
-n
:请求sed不要将模式空间输出到输出流,除非由
p
命令发出请求。

这里有一个
awk
应该可以工作:

$ sed -f sedscr infile
[start] cmd4
dfdafadf
d
afasdf

daf
[stop] cmd4
[start] cmd1
adfadd
dafa
dfdd33r55ae
[stop] cmd1
[start] cmd8
error...

[stop] cmd8
[start] cmd10
exit xx

[stop] cmd10
awk'/^\[start\]/{i=1;删除a}{a[i++]=$0}/^\[stop\]/{for(j=1;j这可能对您有用(GNU-sed):

如果该行以
[start]
[stop]
开头(大写或小写),则打印该行以及任何未以
[
开头的后续行。如果下一行以
[
开头,则循环回到开头并再次检查,否则将其删除

编辑:

另一个答案可能是:

sed ':a;/^\[start\|stop\]/I{:b;$!{n;/^\[/ba;bb}};d' file
编辑:

鉴于现正修订的问题:

sed '/^\[start\]/I{h;d};H;/^\[stop\]/I{x;p;x};d' file

那么你想要什么?在你的例子中预期的输出是什么?@hek2mgl,请不要更改我的
infle
!!!它是贪婪的,这正是OP不想要的:它打印任何不平衡的
[start].[start].[stop]的所有内容
chunk,例如。@jaybee更新了我的帖子。如果OP给出了一个输出示例,这会有很大帮助。这也是为什么我通常总是从命令中添加输出,以查看OP是否需要。当然,你是对的。+1对于你的解决方案,用数组实现sed的保持空间:),但你应该有
/^\[start\]/
as pattern,而不仅仅是/start/。显然(现在是静默的)OP希望它不区分大小写…@jaybee,但您是否测试过它?是的,当然,例如,它输出OP给出的示例的前三行,我想这是不需要的。您的第二个答案(编辑部分)是的,但IMHO与我下面的解决方案没有太大区别(
h;d
而不是
h;n
),谢谢,这是最简洁的方法。解释也很有帮助。当文件包含的[stop]行多于[start]行时,会出现一些问题。请参阅编辑。
sed '/^\[start\]/I{h;d};H;/^\[stop\]/I{x;p;x};d' file
sed '/^\[start\]/I{:a;x;/^\(.*\[stop\][^\n]*\).*/Is//\1/p;x;h;d};H;$ba;d' file