MAC addresses are written in an astonishingly big number of slightly different ways. As long as they are intended for human consumption, that is OK. But if they are used to match on program output, e.g to check the ARP table of a router, the correct format for that router model has to be used. Manual conversion is easy, but nevertheless error-prone. Thus I have written a small AWK script called macfmt to convert from and to the MAC address formats I know. It is included in my Single File Tools collection.
macfmt [-v cap=CASE] [-v format=FORMAT] CASE is one of: lower, upper FORMAT is one of: all, cisco, linux, enterasys, cabletron, broadcom, vmps, netsight, hp, hex, hexprefix, pxe, pgsql, hexpostfix, exos, arista, mikrotik, huawei, ieee, ietf, dell, ftos, dellos9, macos, apple_ios, android, chromeos, ps3, ps4, ps5, switch, wii, xbox, xbox360, windows, windows_arp
$ echo 01:23:45:67:89:ab | macfmt 0123.4567.89ab 01:23:45:67:89:ab 01-23-45-67-89-AB 01:23:45:67:89:AB 0123:4567:89AB 0123.4567.89AB 01.23.45.67.89.AB 012345-6789ab 0123456789ab 0x0123456789ab 01 23 45 67 89 AB 012345:6789ab 0123456789ABh 0123-4567-89ab 01-23-45-67-89-ab 0123456789AB $ echo 01-23-45-67-89-AB | macfmt -v format=linux 01:23:45:67:89:ab $ echo 0123:4567:89AB | macfmt -v format=cisco 0123.4567.89ab $ echo 0123.4567.89ab | macfmt -v format=linux -v cap=upper 01:23:45:67:89:AB
I have developed macfmt on Solaris 10 using its new AWK (/usr/xpg4/bin/awk). It works as well with Gawk, the GNU Project's AWK implementation. I have intended macfmt to work with any POSIX compatible AWK, help in improving compatibility is welcome.
macfmt does not work with mawk versions below 1.3.4, because those did not support character classes in regular expressions. This might be a problem for some Ubuntu users, because mawk was the default AWK interpreter there for a long time. To fix this, install gawk on Ubuntu and change the first line of the script to:
#! /usr/bin/gawk -fUbuntu 20.04 LTS provides mawk version 1.3.4, thus macfmt works there with either gawk or mawk as
/usr/bin/awk
.
On
Debian
GNU/Linux and derivatives thereof like Ubuntu GNU/Linux, the
Debian Alternatives System
(Debian Wiki,
Debian Reference)
can be used to select which AWK implementation provides
/usr/bin/awk
.
I have written a Python script called
macfmt.py,
also included in the
Single File Tools
collection, that accepts MAC addresses either as command line arguments
or on standard input (STDIN). This script prints each input
MAC address in only one format, selectable via the
--format FMT
option.
Gawk supports defining fields by content using FPAT. This enables one-line Gawk programs for MAC address formatting, one for each of the different output formats, e.g.:
gawk 'BEGIN {FPAT="[[:xdigit:]]{2}"};{if(NF==6)print tolower($1 $2 "." $3 $4 "." $5 $6)}'
gawk 'BEGIN {FPAT="[[:xdigit:]]{2}"};{if(NF==6)print tolower($1 ":" $2 ":" $3 ":" $4 ":" $5 ":" $6)}'
gawk 'BEGIN {FPAT="[[:xdigit:]]{2}"};{if(NF==6)print toupper($1 "-" $2 "-" $3 "-" $4 "-" $5 "-" $6)}'
gawk 'BEGIN {FPAT="[[:xdigit:]]{2}"};{if(NF==6)print toupper($1 ":" $2 ":" $3 ":" $4 ":" $5 ":" $6)}'
gawk 'BEGIN {FPAT="[[:xdigit:]]{2}"};{if(NF==6)print toupper($1 $2 ":" $3 $4 ":" $5 $6)}'
gawk 'BEGIN {FPAT="[[:xdigit:]]{2}"};{if(NF==6)print toupper($1 $2 "." $3 $4 "." $5 $6)}'
gawk 'BEGIN {FPAT="[[:xdigit:]]{2}"};{if(NF==6)print toupper($1 "." $2 "." $3 "." $4 "." $5 "." $6)}'
gawk 'BEGIN {FPAT="[[:xdigit:]]{2}"};{if(NF==6)print tolower($1 $2 $3 "-" $4 $5 $6)}'
gawk 'BEGIN {FPAT="[[:xdigit:]]{2}"};{if(NF==6)print tolower($1 $2 $3 $4 $5 $6)}'
gawk 'BEGIN {FPAT="[[:xdigit:]]{2}"};{if(NF==6)print tolower("0x" $1 $2 $3 $4 $5 $6)}'
gawk 'BEGIN {FPAT="[[:xdigit:]]{2}"};{if(NF==6)print toupper($1 $2 $3 $4 $5 $6 "h")}'
gawk 'BEGIN {FPAT="[[:xdigit:]]{2}"};{if(NF==6)print toupper($1 " " $2 " " $3 " " $4 " " $5 " " $6)}'
gawk 'BEGIN {FPAT="[[:xdigit:]]{2}"};{if(NF==6)print toupper($1 $2 $3 ":" $4 $5 $6)}'
In the case that only valid MAC addresses
separated by whitespace are used as input,
POSIX
provides tools for one-line command pipelines using tr
and sed
that fulfill the role of macfmt
.
Each command pipeline is based on the same tr
invocation to
remove all but the hexadecimal digits of the MAC address and conserving
whitespace, followed by case conversion and digit grouping according to
the target format.
tr -cd '[:xdigit:][:space:]' | tr '[:upper:]' '[:lower:]' | sed 's/\([[:xdigit:]]\{4\}\)\([[:xdigit:]]\{4\}\)\([[:xdigit:]]\{4\}\)/\1.\2.\3/g'
tr -cd '[:xdigit:][:space:]' | tr '[:upper:]' '[:lower:]' | sed 's/\([[:xdigit:]]\{2\}\)\([[:xdigit:]]\{2\}\)\([[:xdigit:]]\{2\}\)\([[:xdigit:]]\{2\}\)\([[:xdigit:]]\{2\}\)\([[:xdigit:]]\{2\}\)/\1:\2:\3:\4:\5:\6/g'
tr -cd '[:xdigit:][:space:]' | tr '[:lower:]' '[:upper:]' | sed 's/\([[:xdigit:]]\{2\}\)\([[:xdigit:]]\{2\}\)\([[:xdigit:]]\{2\}\)\([[:xdigit:]]\{2\}\)\([[:xdigit:]]\{2\}\)\([[:xdigit:]]\{2\}\)/\1-\2-\3-\4-\5-\6/g'
tr -cd '[:xdigit:][:space:]' | tr '[:lower:]' '[:upper:]' | sed 's/\([[:xdigit:]]\{2\}\)\([[:xdigit:]]\{2\}\)\([[:xdigit:]]\{2\}\)\([[:xdigit:]]\{2\}\)\([[:xdigit:]]\{2\}\)\([[:xdigit:]]\{2\}\)/\1:\2:\3:\4:\5:\6/g'
tr -cd '[:xdigit:][:space:]' | tr '[:lower:]' '[:upper:]' | sed 's/\([[:xdigit:]]\{4\}\)\([[:xdigit:]]\{4\}\)\([[:xdigit:]]\{4\}\)/\1:\2:\3/g'
tr -cd '[:xdigit:][:space:]' | tr '[:lower:]' '[:upper:]' | sed 's/\([[:xdigit:]]\{4\}\)\([[:xdigit:]]\{4\}\)\([[:xdigit:]]\{4\}\)/\1.\2.\3/g'
tr -cd '[:xdigit:][:space:]' | tr '[:lower:]' '[:upper:]' | sed 's/\([[:xdigit:]]\{2\}\)\([[:xdigit:]]\{2\}\)\([[:xdigit:]]\{2\}\)\([[:xdigit:]]\{2\}\)\([[:xdigit:]]\{2\}\)\([[:xdigit:]]\{2\}\)/\1.\2.\3.\4.\5.\6/g'
tr -cd '[:xdigit:][:space:]' | tr '[:upper:]' '[:lower:]' | sed 's/\([[:xdigit:]]\{6\}\)\([[:xdigit:]]\{6\}\)/\1-\2/g'
tr -cd '[:xdigit:][:space:]' | tr '[:upper:]' '[:lower:]'
tr -cd '[:xdigit:][:space:]' | tr '[:upper:]' '[:lower:]' | sed 's/\([[:xdigit:]]\{12\}\)/0x\1/g'
back to my homepage.