我有一个这样格式的文本文件(它是思科防火墙配置文件):
object-group network group21 network-object host 10.254.3.120 network-object host 10.254.3.121 network-object host 10.254.3.122 object-group network group456_local network-object host 192.168.150.63 network-object host 192.168.150.64 network-object host 192.168.150.76 object-group network group456_proxy network-object host 10.241.150.63 network-object host 10.241.150.64 network-object host 10.241.150.65 object-group network group154 network-object host 10.9.11.45 network-object host 10.9.11.10
注意:是的,网络对象组前面的文件中有空格。
使用Perl,如果它包含单词group456,如何从对象组中提取所有行?我要做的是搜索整个配置文件,如果有一个名为group456的单词,输出打印应该是:
object-group network group456_local network-object host 192.168.150.63 network-object host 192.168.150.64 network-object host 192.168.150.76 object-group network group456_proxy network-object host 10.241.150.63 network-object host 10.241.150.64 network-object host 10.241.150.65
提前感谢您的帮助。
答案 0 :(得分:2)
对行进行分组而不将整个文件读入内存的通用方法:
my @buf;
while (1) {
my $line = <>;
if (!defined($line) || $line !~ /^ /) {
if (@buf) {
...
}
last if !defined($line);
@buf = ();
}
push @buf, $line;
}
在这种情况下,请用
替换缺失的部分print @buf
if $buf[0] =~ /^object-group\s+network\s+\w*group456/;
如果将整个文件读入内存,则更简单。
my $file = do { local $/; <> };
print
for
grep { /^object-group\s+network\s+\w*group456/ }
split(/^(?! )/m, $file);
与前面的答案不同,这些方法不要求块一个接一个,并且不需要知道下一个块将是什么。
答案 1 :(得分:1)
一个简单的解决方案是使用..
运算符来收集设置起点和终点之间的行(例如group2 .. group3 + 1)。必须进一步进一步确保抓住所有线路然后移除最后一条线路。此解决方案假定您要捕获的组始终按顺序排列。
#!perl
use strict;
use warnings;
while (readline(*DATA)) {
next unless /group2\b/ .. /group4\b/;
last if /group4/;
print;
}
__DATA__
object-group network group1
network-object host 10.254.3.120
network-object host 10.254.3.121
network-object host 10.254.3.122
object-group network group2
network-object host 192.168.150.63
network-object host 192.168.150.64
network-object host 192.168.150.76
object-group network group3
network-object host 10.241.150.63
network-object host 10.241.150.64
object-group network group4
network-object host 10.9.11.45
network-object host 10.9.11.10
您可以在接受文本,起始组和结束组的子例程中对此进行概括。
答案 2 :(得分:1)
此解决方案使用功能但丑陋的状态标志技术
输入文件一次读取一行,如果遇到某行,变量$print
(最初 false )设置为 true 以非空格字符开头,包含group456
只要$print
true
请注意use autodie
无需检查open
是否成功
use strict;
use warnings 'all';
use autodie;
use constant FILE => 'firewall.cfg';
open my $fh, '<', FILE;
my $print = 0;
while ( <$fh> ) {
$print = /group456/ if /^\S/;
print if $print;
}
object-group network group456_local
network-object host 192.168.150.63
network-object host 192.168.150.64
network-object host 192.168.150.76
object-group network group456_proxy
network-object host 10.241.150.63
network-object host 10.241.150.64
network-object host 10.241.150.65