0

I have a MAC address that looks like this.

01:AA:BB:0C:D0:E1

I want to convert it to lowercase and strip the leading zeros.

1:aa:bb:c:d0:e1

What's the simplest way to do that in a Bash script?

Patrick McElhaney
  • 57,901
  • 40
  • 134
  • 167

3 Answers3

3
$ echo 01:AA:BB:0C:D0:E1 | sed 's/\(^\|:\)0/\1/g;s/.*/\L\0/'
1:aa:bb:c:d0:e1

\(^\|:\)0 represents either the line start (^) or a :, followed by a 0. We want to replace this by the capture (either line start or :), which removed the 0.

Then, a second substitution (s/.*/\L\0/) put the whole line in lowercase.

$ sed --version | head -1
sed (GNU sed) 4.2.2

EDIT: Alternatively:

echo 01:AA:BB:0C:D0:E1 | sed 's/0\([0-9A-Fa-f]\)/\1/g;s/.*/\L\0/'

This replaces 0x (with x any hexa digit) by x.

EDIT: if your sed does not support \L, use tr:

echo 01:AA:BB:0C:D0:E1 | sed 's/0\([0-9A-Fa-f]\)/\1/g' | tr '[:upper:]' '[:lower:]'
Patrick McElhaney
  • 57,901
  • 40
  • 134
  • 167
rom1v
  • 2,752
  • 3
  • 21
  • 47
  • I get the output `L0`. (GNU bash, version 4.3.42(1)-release (x86_64-apple-darwin15.3.0)) – Patrick McElhaney Jan 27 '17 at 13:42
  • [I can't tell which version of sed I have](https://stackoverflow.com/questions/37639496/how-can-i-check-the-version-of-sed-in-os-x), but it's OSX 10.12.3. This is what ultimately worked: `echo 01:AA:BB:0C:D0:E1 | sed 's/0\([0-9A-F]\)/\1/g' | tr '[:upper:]' '[:lower:]'` – Patrick McElhaney Jan 27 '17 at 13:50
  • can be done in one shot: `echo '01:AA:BB:0C:D0:E1' | sed -E 's/0*([^:]+)/\L\1/g'` – Sundeep Jan 27 '17 at 14:37
2

Here's a pure Bash≥4 possibility:

mac=01:AA:BB:0C:D0:E1
IFS=: read -r -d '' -a macary < <(printf '%s:\0' "$mac")
macary=( "${macary[@]#0}" )
macary=( "${macary[@],,}" )
IFS=: eval 'newmac="${macary[*]}"'
  • The line IFS=: read -r -d '' -a macary < <(printf '%s:\0' "$mac") is the canonical way to split a string into an array,
  • the expansion "${macary[@]#0}" is that of the array macary with leading 0 (if any) removed,
  • the expansion "${macary[@],,}" is that of the array macary in lowercase,
  • IFS=: eval 'newmac="${macary[*]}"' is a standard way to join the fields of an array (note that the use of eval is perfectly safe).

After that:

declare -p newmac

yields

declare -- newmac="1:aa:bb:c:d0:e1"

as required.

gniourf_gniourf
  • 44,650
  • 9
  • 93
  • 104
0

A more robust way is to validate the MAC address first:

mac=01:AA:BB:0C:D0:E1

a='([[:xdigit:]]{2})'  ;  regex="^$a:$a:$a:$a:$a:$a$"
[[ $mac =~ $regex ]] || { echo "Invalid MAC address" >&2; exit 1; }

And then, using the valid result of the regex match (BASH_REMATCH):

set -- $(printf '%x ' $(printf '0x%s ' "${BASH_REMATCH[@]:1}" ))
IFS=: eval 'printf "%s\n" "$*"'

Which will print:

1:aa:bb:c:d0:e1

Hex values without leading zeros and in lowercase.
If Uppercase is needed, change the printf '%x ' to printf '%X '.
If Leading zeros are needed change the same to printf '%02x '.