Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling

Regex overlap in MAC address

by superfrink (Curate)
on Sep 11, 2006 at 19:15 UTC ( #572379=perlquestion: print w/replies, xml ) Need Help??
superfrink has asked for the wisdom of the Perl Monks concerning the following question:

I have a list of MAC addresses from two sources that I want to unique and sort. I discovered that some of the address do not have zero padding and some do. I ran into a problem trying to use a regex to zero pad a MAC address.

My sample MAC:
0:13:46:b:4:31 # input 00:13:46:0b:04:31 # expected output

The regex I tried was:
$mac =~ s/(^|:)([\da-f])(:|$)/${1}0${2}${3}/g;

This gave me:
0:13:46:b:4:31 # input 00:13:46:0b:4:31 # produced 00:13:46:0b:04:31 # expected

My guess is there is an overlap problem because the regex matches and replaces the : charater and so the : is not available to be mactched for the "4" because it was already used by the "b".

I thought about it for a bit and got around the problem without using a regex.

my @parts = split /:/ , $mac; foreach (@parts) { if (length == 1) { $_ = "0" . $_; } } $mac = join ":" , @parts;

Can someone explain why the regex did not work as I expected or how to make it work as desired?

Replies are listed 'Best First'.
Re: Regex overlap in MAC address
by ikegami (Pope) on Sep 11, 2006 at 19:23 UTC
    0:13:46:b:4:31 ^^ First pass ^^^^ Second pass ^^^ Third pass

    You're expecting the regexp to match the same : twice. Use a zero-width lookahead to check for the trailing : or end of string.

    $mac =~ s/(^|:)([0-9a-fA-F])(?=:|$)/${1}0$2/g;

    Better yet, eliminate needless copying.

    $mac =~ s/(^|:)(?=[0-9a-fA-F](?::|$))/${1}0/g;

    Update: Tested. Fixed bug where : would get removed.

    Update: If you really need speed, the following is much faster, but it sacrifices readability:

    $mac =~ s/(?<=:)(?=[0-9a-fA-F](?::|$))/0/g; $mac =~ s/^(?=[0-9a-fA-F](?::|$))/0/;
    Rate orig fast orig 36251/s -- -42% fast 62533/s 72% --
      Hi ikegami could you please rate this too?
      $mac= join ":",map substr("00$_",-2),split/:/,$mac;


        Sure thing

        use Benchmark qw( cmpthese ); our $data = '0:13:46:b:4:31'; cmpthese(-3, { ike_orig => 'my $mac = $data; $mac =~ s/(^|:)(?=[0-9a-fA-F](?::|$)) +/${1}0/g; $mac;', ike_fast => 'my $mac = $data; $mac =~ s/(?<=:)(?=[0-9a-fA-F](?::|$) +)/0/g; $mac =~ s/^(?=[0-9a-fA-F](?::|$))/0/; + $mac;', skeeve => 'my $mac = $data; $mac = join ":", map substr("0$_",-2) +, split/:/, $mac; $mac;', jwkrahn1 => 'my $mac = $data; $mac =~ s/([^:]+)/ sprintf "%02s", $1 + /eg; $mac;', jwkrahn2 => 'my $mac = $data; $mac = join ":", map sprintf( "%02s", + $_ ), split /:/, $mac; $mac;', });
        Rate ike_orig jwkrahn1 skeeve jwkrahn2 ike_fast ike_orig 37908/s -- -3% -29% -31% -43% jwkrahn1 38957/s 3% -- -27% -29% -41% skeeve 53318/s 41% 37% -- -3% -20% jwkrahn2 54879/s 45% 41% 3% -- -18% ike_fast 66551/s 76% 71% 25% 21% --
Re: Regex overlap in MAC address
by VSarkiss (Monsignor) on Sep 11, 2006 at 20:56 UTC
Re: Regex overlap in MAC address
by jwkrahn (Monsignor) on Sep 11, 2006 at 20:12 UTC
    Update: Thanks Skeeve for pointing out that error, it is now fixed.
    $ perl -le' $mac = "0:13:46:b:4:31"; $mac =~ s/([^:]+)/ sprintf "%02x", hex $1 /eg; print $mac; ' 00:13:46:0b:04:31 $ perl -le' $mac = "0:13:46:b:4:31"; $mac = join ":", map sprintf( "%02x", hex ), split /:/, $mac; print $mac; ' 00:13:46:0b:04:31
      Didn't you notice that it fails for hex digits a-f? use "%02s" instead.


Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://572379]
Approved by ikegami
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others imbibing at the Monastery: (6)
As of 2016-10-27 10:18 GMT
Find Nodes?
    Voting Booth?
    How many different varieties (color, size, etc) of socks do you have in your sock drawer?

    Results (358 votes). Check out past polls.