【问题标题】:What is a regular expression for a MAC Address?什么是 MAC 地址的正则表达式?
【发布时间】:2023-01-12 23:32:42
【问题描述】:

在这种格式中:

3D:F2:C9:A6:B3:4F

或者:

3D-F2-C9-A6-B3-4F

【问题讨论】:

    标签: regex


    【解决方案1】:

    标准 (IEEE 802) 格式 在中打印 MAC-48 地址 人类友好的形式是六组 两个十六进制数字,由 连字符 - 或冒号 :

    所以:

    ^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$
    

    【讨论】:

    • 请注意,如果它们与小写十六进制字母一起存储,它将不匹配将组更改为 [0-9A-Fa-f] 以捕获两种情况
    • 你可能还想忽略大小写
    • ^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$
    • 顺便说一句,上面关于“标准格式”的引用来自维基百科,而不是 802.3 标准机构。 IEEE 802-2014 实际上规定连字符对于普通 MAC 地址(§ 8.1 ¶ 3)和冒号对于过时的位反转表示法(¶ 4)。重要的是,在实践中,没有人注意到这一点.我们只是简单地使用一个或另一个,但从不将它们混合在一个单独的书面 MAC 中。
    • 我认为此 RegEx 不正确,因为它还将“3D-F2-C9:A6-B3:4F”分类为有效的 MAC 地址,即使它不正确。正确的应该是:((([a-zA-z0-9]{2}[-:]){5}([a-zA-z0-9]{2}))|(([a- zA-z0-9]{2}:){5}([a-zA-z0-9]{2}))) 这样每次您都可以为整个 MAC 地址选择“:”或“-”。
    【解决方案2】:

    眼睛有点硬,但是这个:

    /^(?:[[:xdigit:]]{2}([-:]))(?:[[:xdigit:]]{2}){4}[[:xdigit:]]{2}$/
    

    将为您的 MAC 符号强制执行所有冒号或所有破折号。

    (例如,更简单的正则表达式方法可能允许 A1:B2-C3:D4-E5:F6,上面拒绝了。)

    【讨论】:

    • 这行得通,但你能解释一下 :xdigit 是什么吗?我注意到你把组 ([-:]) 放在了长度之后,是什么让它要么全是冒号要么全是连字符?
    • @Xaisoft,:xdigit: 是十六进制数字的缩写,或多或少是[a-fA-F0-9] 的另一种说法。 指的是第一个破折号或冒号([-:]) 的捕获组,并且只匹配第一次匹配的内容。
    • +1 适当地使用捕获组和非捕获组,以及使用:xdigit:(即使“速记”仅比[a-fA-F0-9] 短,而等效的/[a-f0-9]/i 更短!)
    • @pilcrow 你能解释一下为什么这个 mac: C8:FD:19:55:E6:3A 失败了吗?这是一个实际的mac地址。我修改了您的正则表达式以仅接受: /^(?:[[:xdigit:]]{2}([:]))(?:[[:xdigit:]]{2}){4}[[:xdigit:]]{2}$/ 谢谢!
    • 在我看来,这是更好的答案,因为它实际上检查了“:”和“-”的混合使用。
    【解决方案3】:

    这个正则表达式几乎匹配所有 mac 格式,包括 Cisco 格式,例如 0102-0304-abcd

    ^([[:xdigit:]]{2}[:.-]?){5}[[:xdigit:]]{2}$
    

    它匹配的示例字符串:

    01:02:03:04:ab:cd
    01-02-03-04-ab-cd
    01.02.03.04.ab.cd
    0102-0304-abcd
    01020304abcd
    

    混合格式也将匹配!

    【讨论】:

    • 这将匹配前五个八位字节中任何一个之后的分隔符,这意味着它将接受例如aa.aa.bbbb.cccc
    • #notAllFormats如果您可以使用 WiFi 访问 OSX 系统,请运行 /System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport -I,并查找 BSSID 行,如果任何八位字节低于 0x10,前导零将被删除(%x%2x 而不是 %02x printf 格式用过的?)
    【解决方案4】:

    分隔符:“:","-",".

    双或单:00 = 0, 0f = f

    /^([0-9a-f]{1,2}[.:-]){5}([0-9a-f]{1,2})$/i
    

    或者

    /^([0-9a-F]{1,2}[.:-]){5}([0-9a-F]{1,2})$/
    


    exm: 00:27:0e:2a:b9:aa, 00-27-0E-2A-B9-AA, 0.27.e.2a.b9.aa ...
    

    【讨论】:

    • 第二个将错误地匹配包含非十六进制字符(例如 g)的字符串。
    • 第二种在大多数风格中都无效,除了支持字符范围排序的 BRE/ERE。但是,对字符范围排序规则的支持因实现而异,因此结果可能会有所不同。
    • 另一件事是这些组必须恰好有 2 个六位数字。
    • 理论上,程序在野外返回的所有 mac 地址都将遵循一些标准,例如每个单独组中的 2 个十六进制数字。然而,一些非标准化的 Unix variants 会在有前导零时缩短输出,在某些情况下只留下 1 个十六进制字符。因此需要 {1,2} 正则表达式
    • 但是,来自[0-9a-F] 的字符集可能应该重写为:[0-9a-fA-F]
    【解决方案5】:

    请注意,Unicode 属性 p{xdigit} 包含 FULLWIDTH 版本。您可能更喜欢p{ASCII_Hex_Digit}

    所问问题的答案可能是最好的答案——前提是你安装了某个古老的 CPAN 模块——输入:

    % perl -MRegexp::Common -lE 'say $RE{net}{MAC}'
    

    我将它输出的特定模式 here 显示为幸运模式编号 13;还有很多其他的。

    这个程序:

    #!/usr/bin/env perl
    use 5.010;
    use strict;
    use warnings qw<FATAL all>;
    
    my $mac_rx = qr{
        ^ (?&MAC_addr) $
        (?(DEFINE)
            (?<MAC_addr>
                    (?&pair) (?<it>  (?&either) )
                (?: (?&pair) k<it> ) {4}
                    (?&pair)
            )
            (?<pair>    [0-9a-f] {2} )
            (?<either>  [:-]        )
        )
    }xi;
    
    while (<DATA>) {
        chomp;
        printf("%-25s %s
    ", $_ => /$mac_rx/ ? "ok" : "not ok");
    }
    
    __END__
    3D:F2:C9:A6:B3:4F
    3D:F2:AC9:A6:B3:4F
    3D:F2:C9:A6:B3:4F:00
    :F2:C9:A6:B3:4F
    F2:C9:A6:B3:4F
    3d:f2:c9:a6:b3:4f
    3D-F2-C9-A6-B3-4F
    3D-F2:C9-A6:B3-4F
    

    生成此输出:

    3D:F2:C9:A6:B3:4F         ok
    3D:F2:AC9:A6:B3:4F        not ok
    3D:F2:C9:A6:B3:4F:00      not ok
    :F2:C9:A6:B3:4F           not ok
    F2:C9:A6:B3:4F            not ok
    3d:f2:c9:a6:b3:4f         ok
    3D-F2-C9-A6-B3-4F         ok
    3D-F2:C9-A6:B3-4F         not ok
    

    这似乎是您正在寻找的那种东西。

    【讨论】:

      【解决方案6】:

      这个link 可能对你有帮助。你可以使用这个:(([0-9A-Fa-f]{2}[-:]){5}[0-9A-Fa-f]{2})|(([0-9A-Fa-f]{4}.){2}[0-9A-Fa-f]{4})

      【讨论】:

        【解决方案7】:

        另见this question

        正则表达式如下:

        ^[0-9A-F]{2}:[0-9A-F]{2}:[0-9A-F]{2}:[0-9A-F]{2}:[0-9A-F]{2}:[0-9A-F]{2}$
        
        ^[0-9A-F]{2}-[0-9A-F]{2}-[0-9A-F]{2}-[0-9A-F]{2}-[0-9A-F]{2}-[0-9A-F]{2}$
        

        【讨论】:

        • 有没有办法通过分组来缩短它?以及如何在没有 2 个单独的正则表达式的情况下将正则表达式组合成一个 : 或一个 - ?
        • netcoder 提供的缩短形式也可以使用。使用一个或另一个可能取决于您是否需要捕获任何 MAC 地址或只是整体验证它。
        • 它需要在整体上进行验证,因此它是否包含所有连字符或所有冒号。如果它包含混合,则它不是有效的 MAC。
        • @Xaisoft:正如我在回答的评论中所说,根据规范混合使用冒号和连字符是有效的。
        • 您从哪个来源获取 MAC 地址可能混合了分隔符?如果它们来自实际机器/NIC,您可能不会遇到该问题。如果是用户输入的数据,只需进行一次字符串替换,使所有的分隔符保持一致即可。
        【解决方案8】:

        非常感谢 @Moshe 上面的 great answer。在做了更多研究之后,我想添加我的额外发现,包括关于 IEEE 802 和在正则表达式中强制使用一致的分隔符。

        用于打印 MAC-48 地址的标准 (IEEE 802) 格式 人类友好的形式是六组两个十六进制数字,分开 经过连字符 -.然而,广泛采用的惯例也允许冒号 :, 和三组四个十六进制数字,由期间。.

        完全感谢 @Moshe 的初始声明,@pilcrowpointing out IEEE 802 仅涵盖连字符。

        这是一个正则表达式,它强制在整个 mac 地址中使用相同的分隔符:

        ^(?:(?:[0-9A-Fa-f]{2}(?=([-:]))(?:[0-9A-Fa-f]{2}){5}))$
        

        Regex101 demo

        这里还有一个完全不使用分隔符的:

        ^(?:(?:[0-9A-Fa-f]{2}(?=([-:]|))(?:[0-9A-Fa-f]{2}){5}))$
        

        Regex101 demo

        【讨论】:

          【解决方案9】:
          /(?:[A-Fa-f0-9]{2}[:-]){5}(?:[A-Fa-f0-9]{2})/
          

          【讨论】:

          • 这是否类似于 pilcrow 的回答,只是没有 :xdigit?
          【解决方案10】:

          如果您使用的是 PHP,您可以使用filter_var()

          // Returns $macAddress, if it's a valid MAC address
          filter_var($macAddress, FILTER_VALIDATE_MAC);
          

          看起来,它支持以下格式的 MAC 地址(x:十六进制数字):

          xx:xx:xx:xx:xx:xx
          xx-xx-xx-xx-xx-xx
          xxxx.xxxx.xxxx
          

          【讨论】:

            【解决方案11】:

            python 版本可能是:

            re.compile(r'A(?:[da-f]{2}[:-]){5}[da-f]{2}Z',re.I)
            

            【讨论】:

              【解决方案12】:
              /^(([a-fA-F0-9]{2}-){5}[a-fA-F0-9]{2}|([a-fA-F0-9]{2}:){5}[a-fA-F0-9]{2}|([0-9A-Fa-f]{4}.){2}[0-9A-Fa-f]{4})?$/
              

              上面的正则表达式验证下面所有的 mac 地址类型:

              01-23-45-67-89-ab
              01:23:45:67:89:ab
              0123.4567.89ab
              

              【讨论】:

              • 我认为这是唯一完整和正确的。
              • 如果您还想匹配无分隔符怎么办?即:0123456789ab
              【解决方案13】:

              我不认为主要的 RegEx 是正确的,因为它也分类

              '3D-F2-C9:A6-B3:4F' 
              

              作为有效的 MAC 地址,即使它不正确。 正确的是:

              ((([a-zA-z0-9]{2}[-:]){5}([a-zA-z0-9]{2}))|(([a-zA-z0-9]{2}:){5}([a-zA-z0-9]{2})))
              

              这样每次您都可以为整个 MAC 地址选择“:”或“-”。

              【讨论】:

              • a-zA-z0-9 更改为 a-fA-F0-9 mac 是十六进制
              猜你喜欢
              • 2011-05-14
              • 1970-01-01
              • 2011-07-14
              • 2022-01-13
              • 2016-12-15
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2010-10-01
              相关资源
              最近更新 更多