4

Hy,

Can someone help me with splitting mac addresses from a log file? :-)

This:

000E0C7F6676

should be:

00:0E:0C:7F:66:76

Atm i split this with OpenOffice but with over 200 MAC Address' this is very boring and slow...

It would be nice if the solution is in bash. :-)

Thanks in advance.

Alan
  • 45,915
  • 17
  • 113
  • 134
fwaechter
  • 885
  • 3
  • 10
  • 19
  • 1
    is it just a list of mac addresses, or is there something else in the file? – falstro Jul 16 '10 at 14:16
  • see http://stackoverflow.com/questions/1187078/how-to-insert-a-new-line-character-after-a-fixed-number-of-characters-in-a-file – tanascius Jul 16 '10 at 14:19
  • There are some other data in the file. It works now with a little "Workaround" and your snippet. Thank you all. :-) – fwaechter Jul 19 '10 at 06:22

7 Answers7

7

A simple sed script ought to do it.

sed -e 's/[0-9A-F]\{2\}/&:/g' -e 's/:$//' myFile

That'll take a list of mac addresses in myFile, one per line, and insert a ':' after every two hex-digits, and finally remove the last one.

falstro
  • 34,597
  • 9
  • 72
  • 86
  • 1
    @Peter; note that this is a fairly brain-damaged way of doing it, and will ONLY work in this particular case. It's only marginally better than `sed -e 's/../&:/g' -e 's/:$//' myFile`, which might actually be better as it's simpler. – falstro Jul 16 '10 at 14:30
  • Yeah i saw it. But it works and the snippet will just be used around 10 times in a year. So it's OK. No need for perfect solution in this case. Thank you for your answer and your comment. :-) – fwaechter Jul 19 '10 at 06:24
  • Might be worth noting that this only works on uppercase hex digits, if you want lower case as well you'd add `a-f` to the brackets right after the `A-Z` so you'd end up with something like `sed -e 's/[0-9A-Fa-f]\{2\}/&:/g' -e 's/:$//' myFile` – Brad P. Dec 18 '15 at 04:24
6
$ mac=000E0C7F6676
$ s=${mac:0:2}
$ for((i=1;i<${#mac};i+=2)); do s=$s:${mac:$i:2}; done
$ echo $s
00:00:E0:C7:F6:67:6
ghostdog74
  • 327,991
  • 56
  • 259
  • 343
  • Do you know of a way to get this working: `${mac//??/??:/}`, that is, do you know how to get whatever got expanded in the substituted part? – falstro Jul 16 '10 at 14:26
  • +1 Wrap this in a `for mac in $(cat file-with-macs.txt); do { ... }` and it's a nice, pure bash solution for the OP's whole problem. – Dan Moulding Jul 16 '10 at 17:02
  • @Dan: No, it should be `while read -r line; do ...; done < file-with-macs.txt`. @roe: See my answer. – Dennis Williamson Jul 16 '10 at 20:38
  • your loop should be `for((i=2;i<${#mac};i+=2))` Notice the mac address in your output is invalid/incorrect. – jesse_b May 23 '22 at 19:32
4

Pure Bash. This snippet

mac='000E0C7F6676'

array=()
for (( CNTR=0; CNTR<${#mac}; CNTR+=2 )); do
  array+=( ${mac:CNTR:2} )
done
IFS=':'
string="${array[*]}"
echo -e "$string"

prints

00:0E:0C:7F:66:76
Fritz G. Mehner
  • 16,550
  • 2
  • 34
  • 41
1
$ perl -lne 'print join ":", $1 =~ /(..)/g while /\b([\da-f]{12})\b/ig' file.log
00:0E:0C:7F:66:76

If you prefer to save it as a program, use

#! /usr/bin/perl -ln    
print join ":" => $1 =~ /(..)/g
  while /\b([\da-f]{12})\b/ig;

Sample run:

$ ./macs file.log 
00:0E:0C:7F:66:76
Greg Bacon
  • 134,834
  • 32
  • 188
  • 245
1

imo, regular expressions are the wrong tool for a fixed width string.

perl -alne 'print join(":",unpack("A2A2A2A2A2A2",$_))' filename

Alternatively,
gawk -v FIELDWIDTHS='2 2 2 2 2 2' -v OFS=':' '{$1=$1;print }'

That's a little funky with the assignment to change the behavior of print. Might be more clear to just print $1,$2,$3,$4,$5,$6

frankc
  • 11,290
  • 4
  • 32
  • 49
1

Requires Bash version >= 3.2

#!/bin/bash
for i in {1..6}
do
    pattern+='([[:xdigit:]]{2})'
done

saveIFS=$IFS
IFS=':'
while read -r line
do
    [[ $line =~ $pattern ]]
    mac="${BASH_REMATCH[*]:1}"
    echo "$mac"
done < macfile.txt > newfile.txt
IFS=$saveIFS

If your file contains other information besides MAC addresses that you want to preserve, you'll need to modify the regex and possibly move the IFS manipulation inside the loop.

Unfortunately, there's not an equivalent in Bash to sed 's/../&:/' using something like ${mac//??/??:/}.

Dennis Williamson
  • 346,391
  • 90
  • 374
  • 439
1
a='0123456789AB'
m=${a:0:2}:${a:2:2}:${a:4:2}:${a:6:2}:${a:8:2}:${a:10:2}

result:

01:23:45:67:89:AB
Zibri
  • 9,096
  • 3
  • 52
  • 44