3

I would like to edit a list of MACs in bl:ab:la:bl:ab:la format >> in to blab.labl.abla format. Each MAC is in a line. I'm new in the use of AWK or SED but I'm almost sure that it can be performed using any of those commands.

Is there any way to set the column position in where a character (a dot) has to be inserted (using sed or awk) in order to accomplish this task?

I've read the sed man page but It didn't get any clear.

1
  • Please edit your question and add an example input file along with the output you expect from that example so we can test our solutions.
    – terdon
    Aug 6, 2022 at 15:07

3 Answers 3

7

With awk:

awk -F: '{print $1$2"."$3$4"."$5$6}'

-F: will set : as the field separator and print $1$2"."$3$4"."$5$6 will print fields $1 and $2 then print a . and so on ... the rest is self explanatory.

Example:

$ echo "bl:ab:la:bl:ab:la" | awk -F: '{print $1$2"."$3$4"."$5$6}'
blab.labl.abla

It can also read from a file like so:

awk -F: '{print $1$2"."$3$4"."$5$6}' file

and modify the file in-place(i.e. edit the original file) like so:

gawk -i inplace -F: '{print $1$2"."$3$4"."$5$6}' file
5

If your inputs are actual MAC addresses, then perl has a Net::MAC module for that (available in Ubuntu via the libnet-mac-perl package):

Ex.

$ echo '01:23:45:67:89:AB' | perl -MNet::MAC -lne '
    my $m = Net::MAC->new("bit_group" => 8, "delimiter" => ":", "mac" => $_);
    print $m->convert("bit_group" => 16, "delimiter", ".")
'
0123.4567.89ab

For arbitrary ASCII text, you could unpack delimited pairs and then string-concatenate pairs of them back together:

$ echo 'bl:ab:la:bl:ab:la' | perl -MList::Util=pairmap -nE '
    say join ".", pairmap { $a . $b } unpack("(A2x)*",$_)
'
blab.labl.abla
4

Manipulating bash parameters

You can do it by manipulating bash parameters, remove the colons, then insert the dots between 4-character strings. See the chapter about 'Parameter Expansion' in man bash for details.

The following shellscript file script can do what you want,

#!/bin/bash

function converter {

 tmp0="$1"
 tmp1=${tmp0//:/}
 #echo "$tmp1"
 tmpstr="${tmp1:0:4}.${tmp1:4:4}.${tmp1:8:4}"
 echo "$tmpstr"
}

#######
# main
#######

if test -s "$1"
then
 while read line
 do
  converter "$line"
 done < "$1"
else
 echo "Usage: ${0##*/} <file-with-list-of-macs>"
fi

Example: I made a small input file macs

ab:cd:ef:gh:ij:kl
12:ab:34:cd:56:ef
qw:er:ty:as:df:gh

and run the following command,

$ ./script macs
abcd.efgh.ijkl
12ab.34cd.56ef
qwer.tyas.dfgh

Command line with sed

You can also use sed doing almost the same as above: remove the colons, then insert the dots after 4-character strings, and finally you must remove the extra dot at the end of each line,

$ < macs sed -e 's/\://g' -e 's/..../&./g' -e 's/\.$//'
abcd.efgh.ijkl
12ab.34cd.56ef
qwer.tyas.dfgh

With a huge input file this solution with sed is significantly faster than the bash shellscript.

< huge.in sed -e 's/\://g' -e 's/..../&./g' -e 's/\.$//' > huge.out

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .