我有一个脚本,该脚本从数据库收集配置数据并将其存储在数组中。我需要打印找到每个接口并打印设备的配置详细信息。我只会发布需要帮助的部分。
首先,这是从数组中提取的内容:
track 2 interface GigabitEthernet1/6 line-protocol
!
!
!
!
!
interface Port-channel10.1
description Enclosure 1 - 3040-1b
switchport
switchport trunk encapsulation dot
switchport trunk allowed vlan 200, 202
switchport mode trunk
logging event link-status
logging event trunk-status
logging event bundle-status
logging event spanning-tree status
shutdown
interface Ethernet1/20
description tx to something
switchport mode trunk
switchport trunk allowed vlan 200-300
spanning-tree guard root
speed 1000
duplex full
interface Bundle-Ether2.1
description Bundle link to something
service-policy input qos-pol1
vrf V17:vodanet
ipv4 address 10.1.1.1 255.0.0.0
encapsulation 250
interface Ethernet1/1
description some interface desc
switchport mode trunk
switchport trunk allowed vlan 200-299
spanning-tree guard root
duplex full
no negotiate auto
clock timezone GMT 2 0
line console
terminal length 48
...
因此,每个接口后面不一定都具有相同数量的配置详细信息。我基本上需要采用这些接口配置中的每一个,并分别打印它们。我将这些存储在较小的config-let平面文件中。因此,我需要从interface ...
打印到下一个界面之前的最后一项,但是我迷失了搜索的方向。这是我的最新尝试,但是仅当我搜索2个不同的开始/结束字符串时才有效,例如:
foreach (@array) {
if (/^interface/) {
$counter = 1;
} elsif (/duplex/) {
$counter =0;
} elsif ($counter) {
print;
}
}
这里的问题是我缺少第一个和最后一个字符串,并且并非所有接口都以duplex
结尾。我当时在考虑使用行interface
的开头,然后在每个双空格分隔项目之后但不确定如何。有人可以帮我找到解决方法吗。
修改
因此,要弄清array
,它只是从数据库中抓取并推送到@array
的行
答案 0 :(得分:1)
问题:数组(@lines
)具有“接口部分”,它们以/^interface/
行开头并一直运行到下一个interface
行。最后一部分在第一行不缩进处停止。解析数组中的接口部分。
一种方法:查找数组interface
中每条@lines
行的索引。然后,连续索引之间的@lines
元素就是接口部分。最后一个单独找到。
my @idx = grep { $lines[$_] =~ /^interface/ } 0..$#lines;
for my $i (0..$#idx-1) {
say "Interface:";
say "\t$_" for @lines[$idx[$i]..$idx[$i+1]-1];
}
# The last interface section stops at the first unindented line
say "Interface:";
for my $i ($idx[-1] .. $#lines) {
last if $lines[$i] =~ /^\S/ and $lines[$i] !~ /^interface/;
say "\t$lines[$i]";
}
最后一个interface
段一直到第一个未缩进的行,如注释中所述。
打印"Interface:"
只是为了在视觉上区分各个部分。例如,可以将每个接口的行添加到arrayref而不是进行打印。在发布的样本上进行了测试。
另一种方法:遍历@lines
,并为每行/^interface/
添加一个新的arrayref到具有所有节的数组。然后将行添加到最后一个arrayref。在第一行未缩进的行上退出,该行不是/^interface/
程序从提交的文件(或lines.txt
)中获取带有问题示例的行。
use warnings;
use strict;
use feature 'say';
use Data::Dump qw(dd);
use Path::Tiny;
my $file = shift @ARGV or 'lines.txt';
my @lines = path($file)->lines({chomp=>1});
my @if_sections; # store arrayrefs with lines for each interface
for (@lines) {
if (/^interface/) {
push @if_sections, [ $_ ]; # add arrayref for new interface
next;
}
elsif (/^\S/) { last }
push @{$if_sections[-1]}, $_; # add lines to the last arrayref
}
dd \@if_sections;
使用方便的Path::Tiny来读取文件。该模块对故障进行检查和检查。
为了方便起见,使用Data::Dump中的dd
来轻松显示数据结构。这是一个具有作为数组引用的元素的数组,因此可以使用它
foreach my $iface (@if_sections) {
say "Interface section:";
foreach my $line (@$iface) {
say $line;
}
}
可以通过多种方式更紧凑地编写内容。
请参见教程perlreftut,然后 复杂的数据结构指南perldsc。