6

What is the correct regular expression for matching MAC addresses ? I googled about that but, most of questions and answers are incomplete. They only provide a regular expression for 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 :. However, this is not the real world case. Many routers, switches and other network devices vendors provide MAC addresses in formats like :

3D:F2:C9:A6:B3:4F //<-- standard 
3D-F2-C9-A6-B3:4F //<-- standard
3DF:2C9:A6B:34F   
3DF-2C9-A6B-34F
3D.F2.C9.A6.B3.4F
3df2c9a6b34f // <-- normalized

What I have until this moment is this:

public class MacAddressFormat implements StringFormat {
  @Override
  public String format(String mac) throws MacFormatException {
    validate(mac);
    return normalize(mac);
  }

  private String normalize(String mac) {

    return mac.replaceAll("(\\.|\\,|\\:|\\-)", "");
  }

  private void validate(String mac) {


    if (mac == null) {
      throw new MacFormatException("Empty MAC Address: !");
    }
    // How to combine these two regex together ? 
    //this one 
    Pattern pattern = Pattern.compile("^([0-9A-Fa-f]{2}[\\.:-]){5}([0-9A-Fa-f]{2})$");
    Matcher matcher = pattern.matcher(mac);
    // and this one ? 
    Pattern normalizedPattern = Pattern.compile("^[0-9a-fA-F]{12}$");
    Matcher normalizedMatcher = normalizedPattern.matcher(mac);

    if (!matcher.matches() && !normalizedMatcher.matches()) {
      throw new MacFormatException("Invalid MAC address format: " + mac);
    }

  }
}

How do yo combine the two regex in the code ?

Community
  • 1
  • 1
Adelin
  • 18,144
  • 26
  • 115
  • 175
  • 2
    Why not just strip all non-hexadecimal, lowercase all the hexadecimal then compare? Then it doesn't matter what crazy format it was in – Patashu May 30 '13 at 06:37
  • Yup, followed by a check whether the value matches 12 hexadecimal characters (your normalized pattern). – Menno May 30 '13 at 06:41

7 Answers7

6

Why so much code? Here is how you can "normalize" your mac address:

mac.replaceAll("[^a-fA-F0-9]", "");

And here is a way to validate it:

public boolean validate(String mac) {
   Pattern p = Pattern.compile("^([a-fA-F0-9][:-]){5}[a-fA-F0-9][:-]$");
   Matcher m = p.matcher(mac);
   return m.find();
}
AlexR
  • 114,158
  • 16
  • 130
  • 208
  • Can you provide and example of a valid MAC address matching the regex above ? 9c:8e:99:f3:bd:1b does not match – Adelin May 30 '13 at 07:37
  • @Test public void regexTest() { String mac = "9c:8e:99:f3:bd:1b"; String replaced = mac.replaceAll("[^a-fA-F0-9]", ""); System.out.println(replaced); Pattern pattern = Pattern.compile("^([a-fA-F0-9][:-]){5}[a-fA-F0-9][:-]$"); Matcher matcher = pattern.matcher(replaced); System.out.println(matcher.matches()); } output is : 9c8e99f3bd1b false – Adelin May 30 '13 at 07:45
  • 2
    I don't quite get that regexp. Is it `m.find()` that make it match the entire MAC? And does it handle `3DF:2C9:A6B:34F` with the `{5}` in there? I kind of thought you needed 5 pairs of [a-fA-F0-9] and [:-], e.g `5:` to match it. Obviously I need to read up on my `Pattern`. :-) Normalize and use `^[a-fA-F0-9]{12}$` would be my approach. – Qben May 30 '13 at 07:53
  • This code does not work at all !! Here a simple gits shows that ... https://gist.github.com/AdelinGhanaem/17bc7c7d1ea41d4d2c78 – Adelin May 31 '13 at 06:30
  • I think the pattern that is shown for validating the MAC address should contain two groups of "0-f" values, that is, "^([a-fA-F0-9][a-fA-F0-9][:-]){5}[a-fA-F0-9][a-fA-F0-9][:-]$". However, this really isn't an answer to the OP, since it only handles the "standard" MAC address format (nn:nn:nn:nn:nn:nn using colons or hyphens). – Andy King Mar 06 '14 at 23:52
  • agree with @Adelin – Paul Praet Jan 19 '21 at 14:02
3

Try this, working perfect..

A MAC address is a unique identifier assigned to most network adapters or network interface cards (NICs) by the manufacturer for identification, IEEE 802 standards use 48 bites or 6 bytes to represent a MAC address. This format gives 281,474,976,710,656 possible unique MAC addresses.

IEEE 802 standards define 3 commonly used formats to print a MAC address in hexadecimal digits:

Six groups of two hexadecimal digits separated by hyphens (-), like 01-23-45-67-89-ab

Six groups of two hexadecimal digits separated by colons (:), like 01:23:45:67:89:ab

Three groups of four hexadecimal digits separated by dots (.), like 0123.4567.89ab

public boolean macValidate(String mac) {
        Pattern p = Pattern.compile("^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$");
        Matcher m = p.matcher(mac);
        return m.find();
}
Neeraj Singh
  • 610
  • 9
  • 15
0

Based on AlexR's answer:

private static Pattern patternMacPairs = Pattern.compile("^([a-fA-F0-9]{2}[:\\.-]?){5}[a-fA-F0-9]{2}$");
private static Pattern patternMacTriples = Pattern.compile("^([a-fA-F0-9]{3}[:\\.-]?){3}[a-fA-F0-9]{3}$");

private static boolean isValidMacAddress(String mac)
{
    // Mac addresses usually are 6 * 2 hex nibbles separated by colons,
    // but apparently it is legal to have 4 * 3 hex nibbles as well,
    // and the separators can be any of : or - or . or nothing.
    return (patternMacPairs.matcher(mac).find() || patternMacTriples.matcher(mac).find());
}

This isn't quite perfect, as it will match something like AB:CD.EF-123456. If you want to avoid that, you can either get more clever than I with making it match the same character in each place, or just split the two patterns into one for each possible separator. (Six total?)

benkc
  • 3,292
  • 1
  • 28
  • 37
0

I know this question is kind of old but i think there is not a really good solution for the problem:

Two steps to do

  1. Change the Mac String to parse to the format of your choice (e.g. xx:xx:xx:xx:xx:xx)
  2. Write a method which validates a string with the format above

Example:

1)

you can easily achieve this by calling

public static String parseMac(String mac) {
    mac = mac.replaceAll("[:.-]", "");

    String res = "";
    for (int i = 0; i < 6; i++) {
        if (i != 5) {
            res += mac.substring(i * 2, (i + 1) * 2) + ":";
        } else {
            res += mac.substring(i * 2);
        }
    }
    return res;
}

:.- are the chars which will be removed from the string

2)

public static boolean isMacValid(String mac) {
    Pattern p = Pattern.compile("^([a-fA-F0-9]{2}[:-]){5}[a-fA-F0-9]{2}$");
    Matcher m = p.matcher(mac);
    return m.find();
}

Ofc you can make the Pattern a local class variable to improve the efficiency of your code.

codewing
  • 674
  • 8
  • 25
0

MAC addresses can be 6 or 20 bytes (infiniband)

The correct regexp assuming the separator is : is

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

We match 5 times XX: optionally we match another 14 times XX: and we match XX

0

MAC Address can be validated with the below code:

private static final String PATTERN = "^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$";
    
private static boolean validateMAC(String mac) {
        Pattern pattern = Pattern.compile(PATTERN);
        Matcher matcher = pattern.matcher(mac);
        return matcher.matches();
    }
Shiv Buyya
  • 3,770
  • 2
  • 30
  • 25
0

Below Regex Pattern will help to manage all kinds of the above listed patterns

"([MACmac]?){1}([:.-]?){1}(([0-9A-Fa-f]{2,3}[:.-]?){4,6})"

here at end i added {4,6} because some pattern as requested below is expecting the group of 3 for 4 time. else if you are looking ONLY for the default on which is usually group of 2 characters 6 times then you can use the below one.

"([MACmac]?){1}([:.-]?){1}(([0-9A-Fa-f]{2}[:.-]?){6})"

hope this helps all.

Sunil KV
  • 763
  • 9
  • 13