Lorand has asked for the wisdom of the Perl Monks concerning the following question:

Hi everyone,

is there a way to wrap a regular expression longer than 80 character across several lines, with functionality unchanged? I have the following:             /^[\da-f][\da-f]:[\da-f][\da-f]:[\da-f][\da-f]:[\da-f][\da-f]:[\da-f][\da-f]:[\da-f][\da-f]$/ for MAC addresses. Or maybe a better way to write it?

Replies are listed 'Best First'.
Re: Long regexp un multiple lines
by davido (Cardinal) on Apr 22, 2004 at 17:41 UTC
    /^[\da-f][\da-f]: [\da-f][\da-f]: [\da-f][\da-f]: [\da-f][\da-f]: [\da-f][\da-f]: [\da-f][\da-f]$/ix

    Or with less typing:

    /^ (?: [\da-f]{2}: ){5} [\da-f]{2} $/ix;

    I used the /x modifier to allow for freeform whitespace within the RE. I used the /i modifier so that hex digits can be represented in either lower or upper case. And in the second example, quantifiers were used to factor out the unnecessary repetition.

    Update: Fixed quantifier on last term.


    Dave

Re: Long regexp un multiple lines
by Enlil (Parson) on Apr 22, 2004 at 17:49 UTC
    Another good place to look for use of the /x modifier is in perlretut. That said the same functionality as in the above stated regular expression could be written more tersely as:
    /^(?:[\da-f]{2}:){5}[/da-f]{2}$/
    or with /x
    /^(?: [/da-f]{2}: ){5} [/da-f]{2} $ /x
    or even shorter if you use qr.
    $x = qr/[\da-f]{2}/;
    (and later on)
    /^(?:$x:){5}$x$/;

    -enlil

      Enlil (et. al.), one of the convenient things about qr// is that it returns a self-contained regex. That means your "later on" code can be /^$x{5}$x$/ It seems weird to me that there's no simpler way to say "pattern X, N times, with pattern Y in between"... you have to write /^(?:XY){N-1}X$/. I wonder if there's something in Regexp::Common for that.
      _____________________________________________________
      Jeff[japhy]Pinyan: Perl, regex, and perl hacker, who'd like a job (NYC-area)
      s++=END;++y(;-P)}y js++=;shajsj<++y(p-q)}?print:??;
        Actually the reason he had to use the (?:$x:){5} approach is because of the colon character that's supposed to delimit each grouping. Your solution leaves that out entirely. Yours will expand to:
        /^(?:[\da-f]{2}){5}(?:[\da-f]{2})$/
        ...note the missing : colons.


        Dave

Re: Long regexp un multiple lines
by Fletch (Bishop) on Apr 22, 2004 at 17:29 UTC

    perldoc perlre, specifically for the /x modifier (and you might check out the parts on quantifiers and on character classes such as [:xdigit:] while you're there).

Re: Long regexp un multiple lines
by ybiC (Prior) on Apr 22, 2004 at 18:29 UTC

    While not directly addressing your explicit question...

    If your underlying problem is validating MAC addresses, then Net::Address::Ethernet might be of some interest.   Particularly the is_address function.

      cheers,
      ybiC

      striving toward Perl Adept
      (it's pronounced "why-bick")

    Update: I looked through Regexp::Common, but found nothing I recognized as parsing MAC address.   8^P

      Yes, when I searched on the net for the regexp, I've seen that module, but why use an extra module, if it is possible without and quite simply? If I needed to check more address types, maybe...
Re: Long regexp un multiple lines
by asdfgroup (Beadle) on Apr 23, 2004 at 00:20 UTC
    6==grep {/^[\da-f]{2}$/} split ':'
Re: Long regexp un multiple lines
by tkil (Monk) on Apr 24, 2004 at 00:08 UTC

    Funny, I'm finding all sorts of great uses for my qr//e idea today...

    my $mac_re = do { my $tmp = join ':', ('[0-9a-f]' x 2) x 6; qr/$tmp/i; };

    This is left intentionally non-anchored, so that you can use it even when searching inside a line:

    my @macs = map { m/($mac_re)/g } qx( /sbin/ifconfig -a );