Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things

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 all is quiet...

How do I use this? | Other CB clients
Other Users?
Others browsing the Monastery: (4)
As of 2017-07-20 23:40 GMT
Find Nodes?
    Voting Booth?
    I came, I saw, I ...

    Results (316 votes). Check out past polls.