Perl question!
Apr. 13th, 2013 05:11 pmQuestion for people who are better at perl than I am (this is most people who program in perl):
So, I've got a script that gets MAC addresses and bridgeport/portdescription info from switches. And there's one subroutine that cleans up the MAC address that the switch gives out. I hand the function a MAC address that's in the form xx:xx:xx:xx:xx:xx, except the switch drops leading zeroes, so it might look like "0:ab:cd:b:ee:ef" instead of "00:ab:cd:0b:ee:ef". The subroutine breaks it up and turns the single digit segments ("a") into a two character segment ("0a") and returns the prettier MAC string. There's also a global variable "prettyMAC", and if that's set, it returns the MAC in xxxx.xxxx.xxxx format instead.
Here's the code:
It works, but I feel like there should be a more elegant way to do this in perl. Thoughts? Suggestions?
Thanks!
So, I've got a script that gets MAC addresses and bridgeport/portdescription info from switches. And there's one subroutine that cleans up the MAC address that the switch gives out. I hand the function a MAC address that's in the form xx:xx:xx:xx:xx:xx, except the switch drops leading zeroes, so it might look like "0:ab:cd:b:ee:ef" instead of "00:ab:cd:0b:ee:ef". The subroutine breaks it up and turns the single digit segments ("a") into a two character segment ("0a") and returns the prettier MAC string. There's also a global variable "prettyMAC", and if that's set, it returns the MAC in xxxx.xxxx.xxxx format instead.
Here's the code:
sub cleanMAC {
my ($mac) = @_;
my @explodedMAC = split(/:/,$mac);
if ($#explodedMAC == 5) {
my $i = 0;
while ($i < 6) {
if (length($explodedMAC[$i]) == 1) {
$explodedMAC[$i] = "0" . $explodedMAC[$i];
}
$i++;
}
} else {
print STDERR "Something is wrong - I have a MAC address I can't parse\n";
die "Borked MAC - aborting\n";
}
if ($prettyMAC) {
$mac = $explodedMAC[0] . $explodedMAC[1] . "." . $explodedMAC[2] . $explodedMAC[3] . "." . $explodedMAC[4] . $explodedMAC[5]
} else {
$mac = $explodedMAC[0] . ":" . $explodedMAC[1] . ":" . $explodedMAC[2] . ":" . $explodedMAC[3] . ":" . $explodedMAC[4] . ":" . $explodedMAC[5];
}
return ($mac);
}It works, but I feel like there should be a more elegant way to do this in perl. Thoughts? Suggestions?
Thanks!
no subject
Date: 2013-04-13 09:50 pm (UTC)(for some reason this isn't printing the hex digits, even though %x is the conversion for hex. I don't have time right now to debug this, but will look into it more later.)
no subject
Date: 2013-04-13 09:59 pm (UTC)$mac = join(":", map { sprintf("%02x", hex($_)) } split(/:/, $mac));
Which works. I think you need the join(); your one-liner also prints a ":" at the end of the string.
no subject
Date: 2013-04-13 10:03 pm (UTC)no subject
Date: 2013-04-13 10:11 pm (UTC)$mac = "01:2:03:4:c:f";
$mac =~ s/\b(\w)\b/0$1/g;
print $mac;
Go go regex. \b = word boundary, so \b\w\b = any single alphanumeric/connector punctuation character. Stick a "0" before it, make the regex global on the string so it matches more than once.
no subject
Date: 2013-04-14 02:09 am (UTC)no subject
Date: 2013-04-14 02:45 am (UTC)All of these solutions work fine in the "happy path" but the tester in me asks "what do you want to happen with malformed inputs?"
Also JWZ re regex but also JWZ re perl! :-)
I would do it using split + hex, reconstruct the MAC as a 48 bit number
use List::Util qw(reduce);
$mac_val = reduce { $a * 256 + $b } split(/:/, $mac)
But that would be wrong. :)
Bryant has the right of it.
no subject
Date: 2013-04-14 04:57 pm (UTC)no subject
Date: 2013-04-14 03:14 am (UTC)Perl might let you do what you want in a single line of 24 characters, but that doesn't mean you *should*.
no subject
Date: 2013-04-14 04:11 am (UTC)And, yeah, it's easily understandable to me as-is. One thing I like about it is in a year or two when I'm cannibalizing this code to write a different script, I'm likely to still understand it. (I actually hacked together the full script, then looked at it and realized it was slightly incomprehensible even when it was all fairly fresh in my mind, at which point I went back and wrote it again putting it into a more coherent format.)
But I realized a while ago that one of the venues for getting better at this sort of thing is to put code out and get feedback on it. So, I am.
I'm unlikely to change the running code, but I figure it's one way to give myself more options for the next script I end up writing.
no subject
Date: 2013-04-15 12:44 pm (UTC)