Regex Perl结果复制问题

Regex Perl结果复制问题,regex,perl,while-loop,Regex,Perl,While Loop,下面是我目前遇到问题的代码块 在某些背景下,我正在编写一个脚本,该脚本将检查我们的网络配置,通过rancid备份,以获得一组默认/需要配置,并将任何错误输出到电子邮件 它的工作原理是读取一个文件(文件名存储为$configs),然后使用regex expresions检查配置行是否存在 下面的代码块应执行以下操作 打开文件句柄,然后在文件打开时,找到以下两个Regex接口GigabitEthernet[1-9]/[0-48]和之间的任何行 然后,它应该检查两个正则表达式之间的行是否存在这些行 记

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

在某些背景下,我正在编写一个脚本,该脚本将检查我们的网络配置,通过rancid备份,以获得一组默认/需要配置,并将任何错误输出到电子邮件

它的工作原理是读取一个文件(文件名存储为$configs),然后使用regex expresions检查配置行是否存在

下面的代码块应执行以下操作

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

然后,它应该检查两个正则表达式之间的行是否存在这些行

记录事件链接状态 记录事件生成树状态 配置速端口 生成树bpduguard启用

如果上面的任何一行不在两个regex d消除器之间,那么它应该将相应的错误消息推送到数组中进行处理,并在以后发送电子邮件

虽然下面的代码块似乎有效(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>")
  }
sw-a-z.z-输入文件

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
!
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
首先,始终在代码顶部使用和pragmas

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

open my $fh, "<", "$fulldir/$configs"
    or die "could not open '$fulldir/$configs': $!";
我可能会这样编写您的代码:

#!/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";
#/usr/bin/perl
严格使用;
使用警告;
子进程\u端口\u检查\u ios{
my($fulldir,$configs)=@;
打开my$fh,“首先,始终在代码顶部使用和pragmas

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

open my $fh, "<", "$fulldir/$configs"
    or die "could not open '$fulldir/$configs': $!";
我可能会这样编写您的代码:

#!/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";
!/usr/bin/perl
严格使用;
使用警告;
子进程\u端口\u检查\u ios{
my($fulldir,$configs)=@;

打开我的$fh,”请提供示例输入数据和预期输出。@Chas.Owens按要求添加。请提供示例输入数据和预期输出。@Chas.Owens按要求添加。因此,这很好,我想添加一个我一直在努力解决的附加功能。某些端口在配置中已关闭,可以安全地忽略这些端口,现在看一下上面的代码块,我猜我需要跳过包含shutdown的记录。这是否可以用一个简单的if语句完成,并将next作为重新排序输出?@Steve是的,你应该可以说
next if/^shutdown$/m
,跳过包含行
shutdown
的记录。这对d来说是有意义的o在跳过非接口记录的代码之前或之后执行此操作(取决于是否需要错误消息或其他内容的接口名称)。因此,这很好,我想添加一个我一直在努力解决的附加功能。有些端口在配置中关闭了,可以安全地忽略这些端口,现在查看上面的代码块,我猜我需要跳过包含关闭的记录。这是否可以用一个简单的if语句完成,以next作为resutling output?@Steve Yes,如果/^shutdown$/m
跳过包含行
shutdown
的记录,您应该可以说
下一步。在跳过非接口记录的代码之前或之后执行此操作是有意义的(取决于您是否需要错误消息或其他内容的接口名称)。