Reputation: 13
First time caller... Longtime reader.
Here is an example of the input that I am working with.
.
.
.
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"
.
.
.
I need to start my range at set vsys "datacenter"
(for example) and stop when I see (2) consecutive exit
.
Usually, I just:
gsed -n '/set vsys "datacenter"/,/exit/p; file
But I need pattern #2 to catch (2) consecutive exit:
gsed -n '/set vsys "datacenter"/,/exit\nexit/p; file
Thus my range match has a multiline pattern for range #2.
I've tried using the sed N command but I'm not doing something right. I will also use this sed command to parse out the vsys sections as needed and these sections always end with (2) consecutive exit
.
As requested, the expected output should look like this:
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
Upvotes: 1
Views: 152
Reputation: 113844
With GNU sed:
sed -r 'H;1h;$!d;x;s/.*(set vsys "datacenter".*exit\nexit).*/\1/' file
For BSD sed, try replacing -r
with -E
.
H;1h;$!d;x;
This is a sed idiom for reading the whole file in at once. If the file is huge, the use a different solution, such as the awk solution below.
s/.*(set vsys "datacenter".*exit\nexit).*/\1/
This extracts the part that we want.
awk '/set vsys "datacenter"/{f=1;} f{print;} /exit/ && last {exit;} {last=0;} f && /exit/{last=1;}' file
/set vsys "datacenter"/{f=1;}
When we see the start line, set flag f
to true (1).
f{print}
If flag f
is true print the line
/exit/ && last {exit;}
If this line contains exit
and the previous line also contained exit
, then we are done and we tell awk to exit
.
{last=0}
Set last to false (0).
f && /exit/{last=1}
This prepares for the next line. If flag f
is true and this line contains exit
, then set last to true (1).
#!/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
The logic here is basically the same as for the awk solution.
Upvotes: 1
Reputation: 58430
This might work for you (GNU sed):
sed '/set vsys "datacenter"/!d;:a;N;/exit\s*\nexit\s*$/!ba' file
If a line doesn't contain the required string delete it. If it does, append the following line and check for the double exit
condition and if not found continue appending lines until the condition is met. Print out the lines held in the pattern space.
Upvotes: 0
Reputation: 203607
Untested since you didn't provide expected output but you need something like this:
awk '
/set vsys "datacenter"/{ f=1; rec=prev="" }
f {
rec=rec $0 ORS
if ( /exit/ && (prev==$0) ) {
printf "%s", rec
f=0
}
prev = $0
}
' file
Upvotes: 1