Perl结果重复问题

时间:2011-08-09 10:10:42

标签: regex perl while-loop

以下是我目前遇到问题的代码块。

一些背景知识,我正在编写一个脚本,它将检查我们的网络配置,通过rancid备份,进行一组默认/需要配置,并将任何错误输出到电子邮件。

它通过读取文件(文件名存储为$ configs)来工作,然后使用正则表达式来检查配置行是否存在。

波纹管代码块应该执行以下操作。

打开文件句柄,然后在文件打开时,找到以下两个Regex接口GigabitEthernet [1-9] / [0-48]和!

之间的任何行。

然后应检查两个正则表达式之间的线是否存在线

记录事件链接状态 记录事件生成树状态 生成树portfast spanning-tree bpduguard enable

如果上述任何一行不在两个正则表达式消除器之间,那么它应该将相应的错误消息推送到数组中进行处理并最终通过电子邮件发送。

虽然下面的代码块似乎有效(sortof),但我最终会有重复的条目,这肯定与while语句中的push语句有关。

通常我会做这样的事情

  while (<FH>){
  if (/(interface GigabitEthernet[1-9]\/[0-48])/../!/){
  $text = $1;
  if ($_ !~ /logging event link-status/){
  $loggingconfigured++
  }
  }
  if ($loggingconfigured++ == 0) {
  push (@PortChecksIOS, "$configs port $text does not have logging event link-status    set<br>")
  }

但是我失去了使用$ text的能力,如果它在while循环之外被取消了。

以下是目前的代码块,欢迎任何建议。但请轻松地对这个perl的东西很新....

sub processPortChecksIOS{
local ($fulldir, $configs, @PortChecksIOS) = @_;
open FH, "$fulldir/$configs" or die $!;


while (<FH>){
if (/(interface GigabitEthernet[1-9]\/[0-48])/../!/){
$text = $1;
        if ($_ =~ /switchport mode access/ && $_ !~ /shutdown/){
            if ($_ !~ /logging event link-status/){
                push (@PortChecksIOS, "$configs port $text does not have logging event link-status set<br>")
            }
            if ($_ !~ /logging event spanning-tree status/) {
                push (@PortChecksIOS, "$configs port $text does not have logging event spanning-tree status set<br>")
            }
            if ($_ !~ /spanning-tree portfast/){
                push (@PortChecksIOS, "$configs port $text does not have spanning-tree portfast set<br>")
            }
            if ($_ !~ /spanning-tree bpduguard enable/){
                push (@PortChecksIOS, "$configs port $text does not have spanning-tree bdpuguard enable set<br>")
            }
            }
        }

   }

return @PortChecksIOS;
}

示例输入sw-a-x.x - 输入文件

interface GigabitEthernet1/0/1
description ftp5
switchport access vlan 51
switchport mode access
load-interval 30
spanning-tree portfast
!
interface GigabitEthernet1/0/2
switchport access vlan 51
switchport mode access
load-interval 30
spanning-tree portfast
!

sw-a-z.z - 输入文件

interface GigabitEthernet1/0/1
description ftp5
switchport access vlan 51
switchport mode access
load-interval 30
spanning-tree portfast
logging event link-status
spanning-tree status
spanning-tree bpduguard enable
!
interface GigabitEthernet1/0/2
switchport access vlan 51
switchport mode access
load-interval 30
spanning-tree portfast
!

预期产出

sw-a-x.x interface GigabitEthernet1/0/1 does not have logging event link-status set
sw-a-x.x interface GigabitEthernet1/0/1 does not have logging event spanning-tree status
sw-a-x.x interface GigabitEthernet1/0/1 does not have spanning-tree bdpuguard enable set
sw-a-x.x interface GigabitEthernet1/0/2 does not have logging event link-status set
sw-a-x.x interface GigabitEthernet1/0/2 does not have logging event spanning-tree status
sw-a-x.x interface GigabitEthernet1/0/2 does not have spanning-tree bdpuguard enable set
sw-a-z.z interface GigabitEthernet1/0/2 does not have logging event link-status set
sw-a-z.z interface GigabitEthernet1/0/2 does not have logging event spanning-tree status
sw-a-z.z interface GigabitEthernet1/0/2 does not have spanning-tree bdpuguard enable set

1 个答案:

答案 0 :(得分:3)

首先,始终使用代码顶部的strictwarnings pragma。

其次,总是使用open的三个参数版本,而不是两个参数版本,并使用词法文件句柄:

open my $fh, "<", "$fulldir/$configs"
    or die "could not open '$fulldir/$configs': $!";

第三,local不按照您的想法行事,使用my创建当前范围内存在的变量。

第四,你真的想在那一秒内匹配012348吗?字符类,或者您想要将整数048匹配?如果你想要更晚的话,你需要说

if (/(interface GigabitEthernet[1-9]\/(?:[1-3]?[0-9]|4[0-8]))\b/ .. /!/) {

我可能会写这样的代码:

#!/usr/bin/perl

use strict;
use warnings;

sub process_port_checks_ios {
    my ($fulldir, $configs) = @_;

    open my $fh, "<", "$fulldir/$configs"
        or die "could not open '$fulldir/$configs': $!";

    my $range = qr/(?:[1-3]?[0-9]|4[0-8])\b/;
    local $/ = "\n!\n"; #records are separated by ! at the start of a line
    my @messages;
    while (<$fh>) {
        #skip records that aren't interfaces
        next unless
            my ($interface) = m{(interface GigabitEthernet[1-9]/$range/$range)};

        my $base = "$configs port $interface does not have";
        unless (/^logging event link-status$/m) {
            push @messages, "$base logging event link-status set";
        }
        unless (/^logging event spanning-tree status$/m) {
            push @messages, "$base logging event spanning-tree status set";
        }
        unless (/^spanning-tree portfast$/m) {
            push @messages, "$base spanning-tree portfast set";
        }
        unless (/^spanning-tree bpduguard enable$/m) {
            push @messages, "$base spanning-tree bdpuguard enable set";
        }
    }

    return @messages;
}

print map { "$_\n" } process_port_checks_ios ".", "data";
相关问题