views:

102

answers:

6

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.

+3  A: 

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.

roe
Thank you, will try this. :-)
fwa
roe
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. :-)
fwa
+3  A: 
$ 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
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?
roe
+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
@Dan: No, it should be `while read -r line; do ...; done < file-with-macs.txt`. @roe: See my answer.
Dennis Williamson
+3  A: 

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
fgm
+1  A: 
$ 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
+1  A: 

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
Beat me to it... knew gawk had to have ananswer :-)
Chris J
+1  A: 

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
Thanks, that's too bad (I mean the `${mac//??/??:/}` part).
roe