in reply to Re: Converting MAC Address
in thread Converting MAC Address

Using:

my $foo = "0:0A:0C:B:B8:F"; $foo =~ s/([0-9A-F])+:?/length($1) < 2?"0$1":$1/ge;

Yields 000A0C0B080F instead of 000A0C0BB80F. I don't understand why it produces that. From what I understand, which is obviously incorrect, it should work.

Any ideas why it doesn't work?

Thanks,

HiFoo

Replies are listed 'Best First'.
Re: Re: Re: Converting MAC Address
by BrowserUk (Patriarch) on Jan 11, 2003 at 00:43 UTC

    Try

    $foo = "0:0A:0C:B:B8:F"; $foo =~ s/([0-9A-F]+)(?::|$)/length($1) < 2?"0$1":$1/ge; print $foo 000A0C0BB80F

    With your version [0-9A-F]+ can just as easily match one hex char as two as the :? part is optional (so that you will match at the end of line. Therefore, it matches the ...:B8:... in two chunks instead of one.

    The version above makes the : or end-of-string mandatory (?::|$) and forces the B8 part to be matched as a single piece rather than two.

    Not necessarially the best way to do it, but it corrects the problem you've identified.

    You can also simplify the right-hand side of the s/// somewhat like this:

    $foo =~ s/([0-9A-F]+)(?::|$)/substr "0$1", -2/ge;

    Examine what is said, not who speaks.

    The 7th Rule of perl club is -- pearl clubs are easily damaged. Use a diamond club instead.

      ++BrowserUK for the simplification of the right hand side, but the only problem with the version I first posted was just the placement of the + outside the capturing parenthesis.

      The :? was only there to remove the : not to delimit (correct word i hope), where the regular expression would stop matching but to remove it if it existed after a string of characters in [0-9A-F]. Thus the (?::|$) is unnecassary, as it will stop when it hits something outside [0-9A-F] anyway, whether it is a colon or the end of the line.

      After further thought the reason:

      $foo =~ s/([0-9A-F])+:?/length($1) < 2?"0$1":$1/ge;
      does not work how it was intended is because ([0-9A-F])+ in the B8 part (the other parts worked because of a fluke of circumstance, but had they all been B8 the error would have been glaringly apparent), but I digress, the reason it did not work for the B8:, is that it first captures the B but the + makes it want more so it continues to with the 8 but since we don't have a + on the inside(ie. ([A-F0-9]+)) the B is tossed, well technically is part of the successful match, but the due to the placement of the + the $1 is now 8. Now, it tries for something else in this character class, but since there is nothing it continues to the next part of the expression, and since the : is the next thing it needs to match (if it is there, hence the ? after the :), it matches successfully, and life goes on, and if no one else learned anything from my spiel, I did, and that counts for something

      -enlil

Re: Re: Re: Converting MAC Address
by theorbtwo (Prior) on Jan 11, 2003 at 01:08 UTC

    In the vein of TMTOWTDI, I think this is clearer:

    my $mac = "0:0A:0C:B:B8:F"; my @mac = split /:/, $mac; $mac = join ':', map {sprintf '%02X', hex $_};
    (BTW, this will reformat things that aren't even close to being valid MACs into things that look a little closer, but still aren't. For example, 'this::isn't:a:mac:foo' would become '00:00:0A:00:0F'.)


    Warning: Unless otherwise stated, code is untested. Do not use without understanding. Code is posted in the hopes it is useful, but without warranty. All copyrights are relinquished into the public domain unless otherwise stated. I am not an angel. I am capable of error, and err on a fairly regular basis. If I made a mistake, please let me know (such as by replying to this node).

      correction$mac = join ':', map {sprintf '%02X', hex $_} @mac; # @mac added poj