我正在编写代码来解析我网络上的所有接口,寻找特定的配置。等。
数据如下:
Interface fa1
mode access
port-security
mac-address sticky
!
interface fa2
mode trunk
!基本上从“^接口”开始,最后是"!“。
我现在的算法是“记录”我需要的数据。
foreach $line (@input) {
if ( $line =~ m/^interface.+\d/ && $line !~ m/interface Embedded-Service-Engine|BRI|TenGigabitEthernet|vlan|Port-channel|ATM|loopback/i) {
$record = 1;
}
#$int ne '' is to handle the rest of the file not in this format
if( $line =~ m/!/ && $int ne '') {
#save data in format 'interface fa2,mode trunk'
#if the interface doesn't have port-security
push(@intlist, join(','split("\r\n",$int))."\n") unless $int =~ m/port-security/;
$record=0;
$int='';
}
if ($record) {
$int.=$line;
}
}虽然这在我的例子中有效,但我想要一个简单的方法来实现它。我搜索了一下,发现你可以使用“.”关于正则表达式
它将我的代码转换为:
@input # contains the file
@interfaces = grep (/^interface.+\d/ .. /!/, @input);这给了我所有的接口数据,问题是现在每一行都是@interfaces数组中的一个元素。然后,我如何将数据拆分,使/^interface.+\d/ .. /!/中的所有内容都成为这个数组中的一个元素,而不需要创建更多的for循环?
目标是将其简化为一个元素,这样我就可以扫描它的接口,我不想查看interface Embedded-Service-Engine|BRI|TenGigabit以及具有正确配置的接口。
发布于 2015-06-16 03:41:56
这是我的最后解决办法。在这种情况下,我将搜索所有端口安全性不等于1的开关端口,这只是一个例子,可以对任何配置进行切换。如果该配置实际应用于这些接口,我也会忽略某些接口。
#!/usr/bin/perl
$MDIR='/currentConfig';
#list of interfaces you don't want to see to filter output
@omit =(
'MANAGEMENT.PORT',
'sup.mgmt',
'Internal.EtherSwitch',
'Router',
'ip address \d',
'STRA'
);
#join with '|' to form the regex
$dontwant = join('|',@omit);
#search criteria
$search='switchport port-security maximum [^1]';
opendir(DIR,$MDIR) or die $!;
@dirContents=readdir DIR;close DIR;
foreach $file (@dirContents) {
open(IN,$MDIR.'/'.$file) or die $!;
#record seperator to !
$/='!';
my @inFile=<IN>; close IN;
#since the record seperator has been changed, '^' won't match beginning of line
my @ints = grep (/\ninterface/i,@inFile);
#set record seperator back to normal
$/="\n";
foreach $int (@ints) {
if ( $int =~ m/$search/i && $int !~ m/$dontwant/) {
push(@finalint,$int);
}
}
}
#just list the interfaces found, i'll use this to make it comma seperated
foreach $elem (@finalint) {
print $elem;
}发布于 2015-06-15 08:29:24
看看$/,因为我认为这会有帮助。它是记录分隔符--默认为\n。
然后,可以将正则表达式应用到当前的“块”中,以提取所需的数据--默认情况下,正则表达式/捕获组应用于隐式变量$_。
例如。
#!/usr/bin/perl
use strict;
use warnings;
local $/ = '!';
while ( <DATA> ) {
my ( $interface ) = m/Interface (\w+)/i;
next if $interface =~ m/Embedded-Service-Engine/;
my ( $mode ) = m/mode (\w+)/;
print "$interface $mode\n";
print "---next record---\n";
}
__DATA__
Interface fa1
mode access
port-security
mac-address sticky
!
interface fa2
mode trunk
!如果您需要将数据保存在其他用途(例如,“流程随走”不合适),那么该作业的工具就是散列。
您可以使用上面的内容--并使用您感兴趣的特定键填充散列--也可以使用地图的魔力来帮助您。
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
local $/ = '!';
my %interfaces;
while ( <DATA> ) {
my ( $interface ) = m/Interface (\w+)/i;
next if $interface =~ m/Embedded-Service-Engine/;
my %interface_values = map { my ( $key, $value ) = split; $key, $value || 1 } grep { /\w/ } split ( "\n" );
$interfaces{$interface} = \%interface_values;
}
print Dumper \%interfaces
__DATA__
Interface fa1
mode access
port-security
mac-address sticky
!
interface fa2
mode trunk
!这条map线基本上是:
\n上的当前记录以获取每一行。port-security )%interfaces。给予类似于:
$VAR1 = {
'fa1' => {
'port-security' => 1,
'mode' => 'access',
'Interface' => 'fa1',
'mac-address' => 'sticky'
},
'fa2' => {
'mode' => 'trunk',
'interface' => 'fa2'
}
};发布于 2015-06-15 09:27:50
散列或hashref将是您可以使用的结果。此外,基于固定结构的读取记录可以使用匹配的正则表达式读取。就像这样:
#!/usr/bin/perl -w
use strict;
use Data::Dumper;
our %MATCH;
*MATCH = \%+;
# read file into variable
my ( $file, $data ) = ( 'interfaces.txt', undef );
open( my $fh, '<', $file ) or die "cannot open file $file";
{
local $/;
$data = <$fh>;
}
close($fh);
print Dumper $data;
my $regex = qr{
(?sm)
interface [^\w\n]+
(?<interface> (\w[^\n]+))
[^\w]+
mode [^\w]+
(?<mode> (\w[^\n]+))
[^\w]+
((?<portsecurity> port-security)
[^\w]+)? # port-security is optional
(mac-address [^\w]+
(?<macaddress> (\w[^\n]+))
)? # mac-address is optional
[^!]*
!
}x;
my $results = {};
while ( $data =~ m/$regex/g ) {
my $interface = $MATCH{interface};
$results->{$interface} = { mode => $MATCH{mode} ? $MATCH{mode} : '' };
$results->{$interface}->{'port-security'} = 1
if defined $MATCH{portsecurity};
$results->{$interface}->{macaddress} = $MATCH{macaddress}
if defined $MATCH{macaddress};
}
print Dumper $results;您输入的结果是:
$VAR1 = {
'fa1' => {
'macaddress' => 'sticky',
'mode' => 'access',
'port-security' => 1
},
'fa2' => {
'mode' => 'trunk'
}
};有一个以接口名称作为键值的散列,使您有机会对所需的接口使用“grep”。
如果您的结构不是固定的--在字段模式、端口安全和mac地址中没有排序--那么您需要一次读取接口记录,然后对每个字段使用单独的regexes来分割字段。
https://stackoverflow.com/questions/30835808
复制相似问题