163

In this format:

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

or:

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

26 Answers 26

339

The standard (IEEE 802) format for printing MAC-48 addresses in human-friendly form is six groups of two hexadecimal digits, separated by hyphens - or colons :.

So:

^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$
15
  • 25
    Note that if they are being stored with lower case hexadecimal letters it will not match change the group to [0-9A-Fa-f] to catch both cases Commented Nov 23, 2010 at 20:24
  • 5
    you probably also want to ignore casing
    – snakehiss
    Commented Nov 23, 2010 at 20:24
  • 5
    ^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$
    – R D
    Commented Mar 25, 2013 at 10:10
  • 3
    As an aside, the quote above concerning "standard format" comes from Wikipedia, not the 802.3 standards body. IEEE 802-2014 actually specifies hyphens for ordinary MAC addresses (§ 8.1 ¶ 3) and colons for the obsolescent bit-reversed notation (¶ 4). Importantly, in practice, no one observes this. We simply use one or the other, but never mix them in a single written MAC.
    – pilcrow
    Commented Jul 14, 2015 at 17:06
  • 3
    I don't think that this RegEx is correct as it also classifies '3D-F2-C9:A6-B3:4F' as a valid MAC Address, even though it is not correct. The correct one would be: ((([a-zA-z0-9]{2}[-:]){5}([a-zA-z0-9]{2}))|(([a-zA-z0-9]{2}:){5}([a-zA-z0-9]{2}))) So that every time you can choose ':' or '-' for the whole MAC address.
    – PyFox
    Commented Apr 5, 2019 at 9:57
34

A little hard on the eyes, but this:

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

will enforce either all colons or all dashes for your MAC notation.

(A simpler regex approach might permit A1:B2-C3:D4-E5:F6, for example, which the above rejects.)

6
  • This works, but can you explain what :xdigit is? and I noticed you put the group ([-:]) after the length, what makes that take either all colons or hyphens?
    – Xaisoft
    Commented Nov 23, 2010 at 20:28
  • 3
    @Xaisoft, :xdigit: is short for hex digit, more-or-less another way of saying [a-fA-F0-9]. The \1 refers to the capture group for the first dash or colon ([-:]), and only matches what matched that first time.
    – pilcrow
    Commented Nov 23, 2010 at 20:33
  • 2
    +1 for using both capturing and non-capturing groups appropriately, and also for using :xdigit: (even though that "shorthand" is only just shorter than [a-fA-F0-9] and equivalent /[a-f0-9]/i is shorter!)
    – gb96
    Commented Dec 21, 2015 at 6:17
  • @pilcrow could you please explain why this mac: C8:FD:19:55:E6:3A fails? It's an actual mac address. I modified your regex to accept : only /^(?:[[:xdigit:]]{2}([:]))(?:[[:xdigit:]]{2}\1){4}[[:xdigit:]]{2}$/ Thanks!
    – Sam
    Commented May 27, 2019 at 15:37
  • 1
    In my mind this is the better answer as it actually checks the mixed use of ":" and "-".
    – Ray Oei
    Commented Oct 11, 2019 at 18:52
12

This regex matches pretty much every mac format including Cisco format such as 0102-0304-abcd

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

Example strings which it matches:

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

Mixed format will be matched also!

2
  • This will match separators after any of the first five octets, meaning that it will accept aa.aa.bbbb.cccc, for example.
    – pilcrow
    Commented Nov 6, 2015 at 4:46
  • 1
    #notAllFormats If you have access to an OSX system with WiFi, run /System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport -I, and look for the BSSID line, if any octet is under 0x10 leading zero is dropped (%x or %2x rather than %02x printf format used?)
    – nhed
    Commented Nov 9, 2017 at 15:24
9

delimiter: ":","-","."

double or single: 00 = 0, 0f = f

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

or

/^([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 ...
5
  • 2
    The second will incorrectly match strings which contain non-hex characters such as g. Commented Feb 25, 2015 at 15:32
  • The second one is not valid in most flavors, except for BRE/ERE, which supports character range collation. However, support for character range collation varies among implementation, so the result may vary.
    – nhahtdh
    Commented May 6, 2015 at 3:14
  • Another thing is that the groups must have exactly 2 hexa-digits.
    – nhahtdh
    Commented May 6, 2015 at 3:30
  • In theory all mac addresses returned by programs in the wild would follow some standard like 2 hex digits in each separate group. However, some non-standardized Unix variants shorten the output when there is a leading zero, leaving only 1 hex char in some cases. Hence the need for the {1,2} regex
    – TrinitronX
    Commented Jun 30, 2016 at 4:11
  • However, the character set from [0-9a-F] should probably be rewritten as: [0-9a-fA-F]
    – TrinitronX
    Commented Jun 30, 2016 at 4:14
5

See this question also.

Regexes as follows:

^[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}$
5
  • 1
    Isn't there a way to shorten it by doing groups? and how can I combine the regex to have either a : or a - without having 2 separate regular expressions?
    – Xaisoft
    Commented Nov 23, 2010 at 20:21
  • The shortened form that netcoder provides will work also. Using one or the other may be based on whether you need to capture any of the MAC address or just validate it on the whole.
    – JYelton
    Commented Nov 23, 2010 at 20:29
  • It needs to be validated on the whole, so if it either contains all hyphens or all colons. If it contains a mix, it is not a valid MAC.
    – Xaisoft
    Commented Nov 23, 2010 at 20:31
  • 2
    @Xaisoft: Like I said in my answer's comment, mixing colons and hyphens is valid according to the specification.
    – netcoder
    Commented Nov 23, 2010 at 20:35
  • What source are you getting MAC addresses from that might have a mix of delimiters? If they are coming from an actual machine/NIC, you likely won't have that issue. If it is user-entered data, just perform a string replace to make all the delimiters consistent.
    – JYelton
    Commented Nov 23, 2010 at 20:36
5

Be warned that the Unicode property \p{xdigit} includes the FULLWIDTH versions. You might prefer \p{ASCII_Hex_Digit} instead.

The answer to the question asked might be best answered — provided you have a certain venerable CPAN module installed — by typing:

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

I show the particular pattern it outputs here as lucky pattern number 13; there are many others.

This program:

#!/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\n", $_ => /$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

generates this output:

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

Which seems the sort of thing you're looking for.

5

You can use this : (([0-9A-Fa-f]{2}[-:]){5}[0-9A-Fa-f]{2})|(([0-9A-Fa-f]{4}\.){2}[0-9A-Fa-f]{4})

0
4

Thanks a lot to @Moshe for the great answer above. After doing some more research I would like to add my extra findings, both in regards to IEEE 802 and enforcing consistent separator usage in regex.

The standard (IEEE 802) format for printing MAC-48 addresses in human-friendly form is six groups of two hexadecimal digits, separated by hyphens -. It is however, widely adopted convention to also allow colon :, and three groups of four hexadecimal digits separated by periods ..

Full credit to @Moshe here for his initial statement, and to @pilcrow for pointing out that IEEE 802 only covers hypens.

Here is a regex that enforces that same separator is used throughout the mac address:

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

Regex101 demo

And here is an additional one that allows for use of no separator at all:

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

Regex101 demo

4

If you are using PHP, you can make use of filter_var():

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

As it seems, it supports MAC addresses in the following formats (x: a hexadecimal digit):

xx:xx:xx:xx:xx:xx
xx-xx-xx-xx-xx-xx
xxxx.xxxx.xxxx
3
/(?:[A-Fa-f0-9]{2}[:-]){5}(?:[A-Fa-f0-9]{2})/
1
  • Is this similar to pilcrow's answer, just without the :xdigit?
    – Xaisoft
    Commented Nov 23, 2010 at 20:35
2

The python version could be:

re.compile(r'\A(?:[\da-f]{2}[:-]){5}[\da-f]{2}\Z',re.I)
2
/^(([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})?$/

The regex above validate all the mac addresses types below :

01-23-45-67-89-ab
01:23:45:67:89:ab
0123.4567.89ab
2
  • I think this is the only one that's complete and correct. Commented Aug 21, 2019 at 13:21
  • What if you also wanted to match with no delimiters? ie: 0123456789ab
    – Calab
    Commented Dec 15, 2022 at 12:22
2

I don't think that the main RegEx is correct as it also classifies

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

as a valid MAC Address, even though it is not correct. The correct one would be:

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

So that every time you can choose ':' or '-' for the whole MAC address.

1
  • 1
    change a-zA-z0-9 to a-fA-F0-9 a mac is hex Commented Sep 13, 2021 at 20:29
2

Maybe the shortest possible, in PCRE (Perl-Compatible Regular Expressions, e.g. used in PHP):

/([\da-f]{2}[:-]){5}[\da-f]{2}/i
1

to match both 48-bit EUI-48 and 64-bit EUI-64 MAC addresses:

/\A\h{2}([:\-]?\h{2}){5}\z|\A\h{2}([:\-]?\h{2}){7}\z/

where \h is a character in [0-9a-fA-F]

or:

/\A[0-9a-fA-F]{2}([:\-]?[0-9a-fA-F]{2}){5}\z|\A[0-9a-fA-F]{2}([:\-]?[0-9a-fA-F]{2}){7}\z/

this allows '-' or ':' or no separator to be used

1
  • In PCRE \h is horizontal whitespace (e.g. tab or space, but not CR or LF)
    – miken32
    Commented Jan 12, 2023 at 17:05
1

A mac address can be 48 bits or 64 bits.

ad:12:13:fc:14:ee // 48 bit, with colons
ad-12-13-fc-14-ee // 48 bit, with dashes
ad1213fc14ee      // 48 bit, without any delimiter
AD:12:13:FC:14:EE // 48 bit, uppercase.

AD:12:13:FC:14:EE:FF:FF // 64 bit, uppercase
ad:12:13:fc:14:ee:13:ad // 64 bit, lowercase
ad-12-13-fc-14-ee-ff-ad // 64 bit, with dashes
ad1213fc14eeffae        // 64 bit, without any delimter

If you are looking for a regular expression that can validate both and all the above cases (which are valid) the following would work:

For 48 bit we can use this:

^[0-9A-Fa-f]{2}([:-]?)(?:[0-9A-Fa-f]{2}\1){4}[0-9A-Fa-f]{2}$

For 64 bit we can use this:

^[0-9A-Fa-f]{2}([:-]?)(?:[0-9A-Fa-f]{2}\1){6}[0-9A-Fa-f]{2}$

If you are looking for a single regex to validate both kinds of mac addresses, use an OR operator to concat them.

1
/^[\da-f]{2}([-:])([\da-f]{2}\1){4}[\da-f]{2}$/i

It uses backreferencing to ensure no mix between : and - is used.

The i flag makes it case insensitive.

Also, you might not need non-capturing groups, so you can make it a bit less complex.

matches

02:32:a3:fa:3b:03
02-32-a3-fa-3b-03
02-32-A3-FA-3B-03

won't match

02-32-A3-FA-3B
02:32:a3:fa:3b:03a
02-32:a3:fa:3b:03
02:32:a3:fa-3b:03
02-32-A3-FA-3B-03-

In javascript, you can also construct it from multiple regexes like this, might be more readable:

const macRegex1 = /^(?:[\da-f]{2}[-]){5}(?:[\da-f]{2})$/;
const macRegex2 = /^(?:[\da-f]{2}[:]){5}(?:[\da-f]{2})$/;
const macRegex = new RegExp(`^${ macRegex1.source }|${ macRegex2.source }$`, 'i');
0

You can use following procedure by passing mac address for validation,

private static final String MAC_PATTERN = "^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$";

private boolean validateMAC(final String mac){          
    Pattern pattern = Pattern.compile(MAC_PATTERN);
    Matcher matcher = pattern.matcher(mac);
    return matcher.matches();             
}
0

PHP Folks:

print_r(preg_match('/^(?:[0-9A-F]{2}[:]?){5}(?:[0-9A-F]{2}?)$/i', '00:25:90:8C:B8:59'));

Need Explanation: http://regex101.com/r/wB0eT7

0

As a MAC address can be 6 or 20 bytes (infiniband, ...) the correct answer is:

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

you can replace : with [:-.]? if you want different separators or none.

0

This could be used tested in sublime with my MAC address This solution will only work with ideal MAC address That will look like this.. XX:XX:XX:XX:XX:XX

(([a-fA-F0-9]{2}[:]){5}[a-fA-F0-9]{2})
0

Cisco format:

([0-9A-Fa-f]){4}\.([0-9A-Fa-f]){4}\.([0-9A-Fa-f]){4}

Matches:

1111.abcd.2222
-1

If you need spaces between numbers, like this variant

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

The regex changes to

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

This one is a small one:

(([0-9A-F]{2}[:-]?){6})

Have in mind, that weird mix of several chars or separators could pass.

-1

I'm going to pile on with an answer here because there is no single solution to scan both 48-bit and 64-bit MAC addresses in one regex, and many of the other solutions allow mixed delimiters or can't handle no delimiters. I also took advantage of the 'ignore-case' flag to shorten the basic hexadecimal character group that appears three times here:

/[\da-f]{2}(?=([-:]?))((\1[\da-f]{2}){2})?(\1[\da-f]{2}){5}/gi

[\da-f] is the shortest way to specify hexadecimal digits, scan upfront for two of them. Then do a lookahead to load up capture group 1 with the delimiter you want to use (or none). Then create an optional pair of hexadecimal pairs to handle the 64-bit case. Then finish with 5 hexadecimal pairs. Once again specify the /i flag to ignore case on the a-f.

If I were implementing this, I would also add a negative lookbehind near the beginning and a negative lookahead at the end to ensure I rejected excess hex-delimiter pairs, but that just complicates the answer and not all regex implementations handle lookbehinds or have all the same features, so I left that out.

Here's Regex101 on @Shwetabh 's example set. enter image description here

-5

the best answer is for mac address validation regex

^([0-9a-fA-F][0-9a-fA-F]:){5}([0-9a-fA-F][0-9a-fA-F])$
0

Not the answer you're looking for? Browse other questions tagged or ask your own question.