【问题标题】:Perl REGEX on mac addressMac地址上的Perl REGEX
【发布时间】:2014-03-21 06:56:36
【问题描述】:

我正在通过 perl 脚本在 cisco 交换机上使用命令“show mac-address-table dynamic”。相同的输出如下:

Legend: * - primary entry
    age - seconds since last seen
    n/a - not available

vlan   mac address     type    learn     age              ports
------+----------------+--------+-----+----------+--------------------------
*   14  782b.cb87.b085   dynamic  Yes          5   Gi4/39
*  400  0017.c59a.23aa   dynamic  Yes         15   Gi3/37
*  400  0017.c59a.23aa   dynamic  Yes          5   Gi1/27
*  400  0017.c50f.704d   dynamic  Yes          5   Gi13/19
*  400  0006.8b05.a915   dynamic  Yes         10   Gi5/29
*  400  c0ea.e414.2f29   dynamic  Yes         10   Gi3/37
*  400  0017.c53e.166d   dynamic  Yes          5   Gi1/12

我正在编写一个脚本,它只取出具有初始前 4 位数字的 mac 地址,例如 0017.c5 或 0006b 或 c0ea.e4。此外,它应该显示它们重复的次数。我尝试编写以下代码:

for my $line (@ver) {
    if (my ($mac_addr) = $line =~ /((?:[0-9a-f]{4}\.){2}[0-9a-f]{4})/) {
        $mac_addr = $1;
        if ($mac_addr =~ m/^(0017.c5)[0-9a-f]{2}.[0-9a-f]{4}/ or $mac_addr =~ m/^(c0ea.e5)[0-9a-f]{2}.[0-9a-f]{4}/ or $mac_addr =~ m/^(0006.b)[0-9a-f]{3}.[0-9a-f]{4}/){
            push (@sonic_macaddr, $mac_addr);
            for $it (@sonic_macaddr){
                $uniq{$it}++;
            }
        }
    }
}
print (Dumper(\%uniq));

我没有得到所需的结果。请问有人可以指导我哪里出错了吗?谢谢。

【问题讨论】:

    标签: regex perl


    【解决方案1】:

    这个匹配总是失败的:

    $mac_addr =~ m/^(0017.c5)[.]/
    

    这会查找您想要的前缀,后跟一个句点。您的 mac 地址都不会在第 8 个字符处有句点。

    也许以下对脚本的修改会对您有所帮助:

    use strict;
    use warnings;
    
    my @ver = <DATA>;
    
    my @mac_prefixes = qw(0017.c5 c0ea.e5 0006.b);
    my $mac_prefixes = '(?:' . join('|', map quotemeta, @mac_prefixes) . ')';
    
    my @sonic_macaddr;
    my %uniq;
    
    for my $line (@ver) {
        if (my ($mac_addr) = $line =~ /((?:[0-9a-f]{4}\.){2}[0-9a-f]{4})/) {
            $mac_addr = $1;
            if ($mac_addr =~ m/^($mac_prefixes)/){
                my $prefix = $1;
                push (@sonic_macaddr, $mac_addr);
                $uniq{$prefix}++;
            }
        }
    }
    
    use Data::Dump;
    dd \%uniq;
    dd \@sonic_macaddr;
    
    __DATA__
    Legend: * - primary entry
        age - seconds since last seen
        n/a - not available
    
    vlan   mac address     type    learn     age              ports
    ------+----------------+--------+-----+----------+--------------------------
    *   14  782b.cb87.b085   dynamic  Yes          5   Gi4/39
    *  400  0017.c59a.23aa   dynamic  Yes         15   Gi3/37
    *  400  0017.c59a.23aa   dynamic  Yes          5   Gi1/27
    *  400  0017.c50f.704d   dynamic  Yes          5   Gi13/19
    *  400  0006.8b05.a915   dynamic  Yes         10   Gi5/29
    *  400  c0ea.e414.2f29   dynamic  Yes         10   Gi3/37
    *  400  0017.c53e.166d   dynamic  Yes          5   Gi1/12
    

    【讨论】:

    • 您想如何计算它们?您是否希望每个前缀都单独计数?
    • 地图quotemeta是什么意思?你能解释一下吗?谢谢。
    • 查找quotemeta。在将常量插入正则表达式时,它是一个重要的工具,因为它会转义所有正则表达式的特殊字符。在这种情况下,您的 mac 前缀中的所有 . 都将被转义,因此它们将不再匹配任何字符。如果你想看到它的实际效果,只需测试它:my @test = map quotemeta, @mac_prefixes; print "@test\n"
    【解决方案2】:

    首先,您的正则表达式有问题。只需从正则表达式中删除 [.]。

    其次,您将结果推入@sonic_macaddr 数组,然后为每场比赛增加$uniq。它给你错误的计数。所以删除那部分。

    这是你的 if 块在修改后的样子。

    if ($mac_addr =~ m/^(0017.c5)/ or $mac_addr =~ m/^(c0ea.e5)/ or $mac_addr =~ m/^(0006.b)/){
        $uniq{$mac_addr}++;
    }
    

    样本数据的输出:

    $VAR1 = {
          '0017.c53e.166d' => 1,
          '0017.c59a.23aa' => 2,
          '0017.c50f.704d' => 1
        };
    

    【讨论】:

    • 谢谢。给你错误的计数是什么意思?它给出了什么计数?谢谢。
    • 你每次都在做for $it (@sonic_macaddr){,导致计数错误。我可能错了,因为你实现了代码。
    • 谢谢。您的 if 条件是否应该保留在 for 循环中?或独立,因为我没有得到想要的结果。谢谢
    • @deep 只需将你的 if 块 if ($mac_addr =~ m/^($mac_prefixes)/){... 替换为我的。看看结果是否正确。
    猜你喜欢
    • 2021-06-18
    • 1970-01-01
    • 2015-07-16
    • 2016-04-18
    • 2022-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-21
    相关资源
    最近更新 更多