sed - 范围匹配 - 范围的一侧是多行模式
sed - range match - one side of the range is a multiline pattern
第一次来电...很长时间reader。
这是我正在使用的输入示例。
.
.
.
exit
exit
set vsys "dr-site"
set vsys-id 2
set vrouter "dr-site-vr"
unset auto-route-export
exit
set service "service1"
set service "service2"
set zone id 101 "Trust1"
set zone id 201 "Untrust1"
set zone id 301 "DMZ1"
set interface "ethernet3/1.3"
set interface "ethernet3/1.4"
set interface "ethernet3/1.6"
set route 0.0.0.0/0
set address "Untrust1"
set address "Trust1"
set address "DMZ1"
set group address "Untrust1"
set group address "Trust1"
set group address "DMZ1"
set group service
set policy id 100
exit
set policy id 200
exit
set policy id 300
exit
set policy id 400
exit
exit
set vsys "datacenter"
set vsys-id 1
set vrouter "datacenter-vr"
unset auto-route-export
exit
set service "service1"
set service "service2"
set zone id 100 "Trust"
set zone id 200 "Untrust"
set zone id 300 "DMZ"
set interface "ethernet3/1.5"
set interface "ethernet3/1.2"
set interface "ethernet3/1.1"
set route 0.0.0.0/0
set address "Untrust"
set address "Trust"
set address "DMZ"
set group address "Untrust"
set group address "Trust"
set group address "DMZ"
set group service
set policy id 100
exit
set policy id 200
exit
set policy id 300
exit
set policy id 400
exit
exit
set vsys "other"
.
.
.
我需要从 set vsys "datacenter"
开始我的范围(例如)并在我看到 (2) 个连续的 exit
时停止。
通常,我只是:
gsed -n '/set vsys "datacenter"/,/exit/p; file
但我需要模式 #2 来捕捉 (2) 连续退出:
gsed -n '/set vsys "datacenter"/,/exit\nexit/p; file
因此我的范围匹配具有范围 #2 的多行模式。
我试过使用 sed N 命令,但我没有做正确的事。我还将使用此 sed 命令根据需要解析出 vsys 部分,这些部分始终以 (2) 连续 exit
.
结尾
根据要求,预期输出应如下所示:
set vsys "datacenter"
set vsys-id 1
set vrouter "datacenter-vr"
unset auto-route-export
exit
set service "service1"
set service "service2"
set zone id 100 "Trust"
set zone id 200 "Untrust"
set zone id 300 "DMZ"
set interface "ethernet3/1.5"
set interface "ethernet3/1.2"
set interface "ethernet3/1.1"
set route 0.0.0.0/0
set address "Untrust"
set address "Trust"
set address "DMZ"
set group address "Untrust"
set group address "Trust"
set group address "DMZ"
set group service
set policy id 100
exit
set policy id 200
exit
set policy id 300
exit
set policy id 400
exit
exit
使用 sed:
使用 GNU sed:
sed -r 'H;1h;$!d;x;s/.*(set vsys "datacenter".*exit\nexit).*//' file
对于 BSD sed,尝试将 -r
替换为 -E
。
工作原理
H;1h;$!d;x;
这是一次读取整个文件的 sed 习惯用法。如果文件很大,请使用不同的解决方案,例如下面的 awk 解决方案。
s/.*(set vsys "datacenter".*exit\nexit).*//
这提取了我们想要的部分。
使用 awk
awk '/set vsys "datacenter"/{f=1;} f{print;} /exit/ && last {exit;} {last=0;} f && /exit/{last=1;}' file
工作原理
/set vsys "datacenter"/{f=1;}
当我们看到起始行时,将标志 f
设置为真 (1)。
f{print}
如果标志 f
为真打印行
/exit/ && last {exit;}
如果这一行包含exit
并且前一行也包含exit
,那么我们就完成了,我们告诉awk到exit
.
{last=0}
将 last 设置为 false (0)。
f && /exit/{last=1}
这为下一行做准备。如果标志 f
为真且此行包含 exit
,则将 last 设置为真 (1)。
使用python3
#!/usr/bin/python3
f = False
last = False
with open('file', 'r') as fhandle:
for line in fhandle:
if 'set vsys "datacenter"' in line:
f = True
if f:
print(line, end="")
if last and 'exit' in line:
break
last = False
if f and 'exit' in line:
last = True
此处的逻辑与 awk 解决方案基本相同。
未经测试,因为您没有提供预期的输出,但您需要这样的东西:
awk '
/set vsys "datacenter"/{ f=1; rec=prev="" }
f {
rec=rec [=10=] ORS
if ( /exit/ && (prev==[=10=]) ) {
printf "%s", rec
f=0
}
prev = [=10=]
}
' file
这可能适合您 (GNU sed):
sed '/set vsys "datacenter"/!d;:a;N;/exit\s*\nexit\s*$/!ba' file
如果某行不包含所需的字符串,请将其删除。如果是,则追加以下行并检查双 exit
条件,如果未找到,则继续追加行直到满足条件。打印出模式 space.
中的行
第一次来电...很长时间reader。
这是我正在使用的输入示例。
.
.
.
exit
exit
set vsys "dr-site"
set vsys-id 2
set vrouter "dr-site-vr"
unset auto-route-export
exit
set service "service1"
set service "service2"
set zone id 101 "Trust1"
set zone id 201 "Untrust1"
set zone id 301 "DMZ1"
set interface "ethernet3/1.3"
set interface "ethernet3/1.4"
set interface "ethernet3/1.6"
set route 0.0.0.0/0
set address "Untrust1"
set address "Trust1"
set address "DMZ1"
set group address "Untrust1"
set group address "Trust1"
set group address "DMZ1"
set group service
set policy id 100
exit
set policy id 200
exit
set policy id 300
exit
set policy id 400
exit
exit
set vsys "datacenter"
set vsys-id 1
set vrouter "datacenter-vr"
unset auto-route-export
exit
set service "service1"
set service "service2"
set zone id 100 "Trust"
set zone id 200 "Untrust"
set zone id 300 "DMZ"
set interface "ethernet3/1.5"
set interface "ethernet3/1.2"
set interface "ethernet3/1.1"
set route 0.0.0.0/0
set address "Untrust"
set address "Trust"
set address "DMZ"
set group address "Untrust"
set group address "Trust"
set group address "DMZ"
set group service
set policy id 100
exit
set policy id 200
exit
set policy id 300
exit
set policy id 400
exit
exit
set vsys "other"
.
.
.
我需要从 set vsys "datacenter"
开始我的范围(例如)并在我看到 (2) 个连续的 exit
时停止。
通常,我只是:
gsed -n '/set vsys "datacenter"/,/exit/p; file
但我需要模式 #2 来捕捉 (2) 连续退出:
gsed -n '/set vsys "datacenter"/,/exit\nexit/p; file
因此我的范围匹配具有范围 #2 的多行模式。
我试过使用 sed N 命令,但我没有做正确的事。我还将使用此 sed 命令根据需要解析出 vsys 部分,这些部分始终以 (2) 连续 exit
.
根据要求,预期输出应如下所示:
set vsys "datacenter"
set vsys-id 1
set vrouter "datacenter-vr"
unset auto-route-export
exit
set service "service1"
set service "service2"
set zone id 100 "Trust"
set zone id 200 "Untrust"
set zone id 300 "DMZ"
set interface "ethernet3/1.5"
set interface "ethernet3/1.2"
set interface "ethernet3/1.1"
set route 0.0.0.0/0
set address "Untrust"
set address "Trust"
set address "DMZ"
set group address "Untrust"
set group address "Trust"
set group address "DMZ"
set group service
set policy id 100
exit
set policy id 200
exit
set policy id 300
exit
set policy id 400
exit
exit
使用 sed:
使用 GNU sed:
sed -r 'H;1h;$!d;x;s/.*(set vsys "datacenter".*exit\nexit).*//' file
对于 BSD sed,尝试将 -r
替换为 -E
。
工作原理
H;1h;$!d;x;
这是一次读取整个文件的 sed 习惯用法。如果文件很大,请使用不同的解决方案,例如下面的 awk 解决方案。
s/.*(set vsys "datacenter".*exit\nexit).*//
这提取了我们想要的部分。
使用 awk
awk '/set vsys "datacenter"/{f=1;} f{print;} /exit/ && last {exit;} {last=0;} f && /exit/{last=1;}' file
工作原理
/set vsys "datacenter"/{f=1;}
当我们看到起始行时,将标志
f
设置为真 (1)。f{print}
如果标志
f
为真打印行/exit/ && last {exit;}
如果这一行包含
exit
并且前一行也包含exit
,那么我们就完成了,我们告诉awk到exit
.{last=0}
将 last 设置为 false (0)。
f && /exit/{last=1}
这为下一行做准备。如果标志
f
为真且此行包含exit
,则将 last 设置为真 (1)。
使用python3
#!/usr/bin/python3
f = False
last = False
with open('file', 'r') as fhandle:
for line in fhandle:
if 'set vsys "datacenter"' in line:
f = True
if f:
print(line, end="")
if last and 'exit' in line:
break
last = False
if f and 'exit' in line:
last = True
此处的逻辑与 awk 解决方案基本相同。
未经测试,因为您没有提供预期的输出,但您需要这样的东西:
awk '
/set vsys "datacenter"/{ f=1; rec=prev="" }
f {
rec=rec [=10=] ORS
if ( /exit/ && (prev==[=10=]) ) {
printf "%s", rec
f=0
}
prev = [=10=]
}
' file
这可能适合您 (GNU sed):
sed '/set vsys "datacenter"/!d;:a;N;/exit\s*\nexit\s*$/!ba' file
如果某行不包含所需的字符串,请将其删除。如果是,则追加以下行并检查双 exit
条件,如果未找到,则继续追加行直到满足条件。打印出模式 space.