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

Starting with
use constant DLE => 0x10;
I would like to contruct a regular expression that matches when the first charater *is* a DLE and the second character is anything but a DLE. I'm having trouble, because I doubt that variables are interpolated in a character class:
my $dle = chr(DLE); $msg =~ /\A$dle[^$dle]/;
I'd be interested in any alternatives, as long as the DLE is defined symbolically and not "hard coded". Thanks !

Replies are listed 'Best First'.
•Re: Interpolation in character class
by merlyn (Sage) on Oct 02, 2003 at 16:37 UTC
Re: Interpolation in character class
by dragonchild (Archbishop) on Oct 02, 2003 at 16:49 UTC
    merlyn is right (as he almost always is). However, this sounds like a good case for negative look-behind.
    $msg =~ /(\A$dle)(?<!\1)/;

    ------
    We are the carpenters and bricklayers of the Information Age.

    The idea is a little like C++ templates, except not quite so brain-meltingly complicated. -- TheDamian, Exegesis 6

    Please remember that I'm crufty and crochety. All opinions are purely mine and all code is untested, unless otherwise specified.

      That seems to generate a "variable length lookbehind not implemented" error :( Also, I don't understand why we are looking *behind*, don't we want to test the second string character with look *ahead* ? If so, how do we confine the lookahead test to only the *next* character ? Doesn't it look all the way to the end of the string ? Thanks, Scott.
        That'll teach me to blab about features I don't know without testing them first. Yes, positive lookahead would definitely be possible. You'd have to flip your test, though.
        $x = 'aba'; print $x =~ /(.)(?=\1)/ ? "double!\n" : "not double!\n"; $x = 'abba'; print $x =~ /(.)(?=\1)/ ? "double!\n" : "not double!\n"; ---- not double! double!

        ------
        We are the carpenters and bricklayers of the Information Age.

        The idea is a little like C++ templates, except not quite so brain-meltingly complicated. -- TheDamian, Exegesis 6

        Please remember that I'm crufty and crochety. All opinions are purely mine and all code is untested, unless otherwise specified.

Re: Interpolation in character class
by Aristotle (Chancellor) on Oct 02, 2003 at 20:23 UTC
    They are interpolated. To make sure it always works, don't forget to quotemeta the DLE.
    use constant DLE => chr(0x10); my $rx = do { local $_ = quotemeta DLE; qr/ \A $_ [^$_] /x }; $msg =~ $rx;

    Makeshifts last the longest.

Re: Interpolation in character class
by sandfly (Beadle) on Oct 02, 2003 at 20:18 UTC
    The perlretut man page says "If you've been around Perl a while, all this talk of escape sequences may seem familiar. Similar escape sequences are used in double-quoted strings and in fact the regexps in Perl are mostly treated as double-quoted strings. This means that variables can be used in regexps as well. Just like double-quoted strings, the values of the variables in the regexp will be substituted in before the regexp is evaluated for matching purposes."

    So the answer to your question is that your construction works because you would expect a double-quoted string to work that way. You could also use the octal excape syntax: /\A\020[^\020]/.

    The reason \x{$a} doesn't work is the same reason that it doesn't work in a double-quoted string - probably that the double-quoted string interpolation mechanism is single-pass and not recursive. (This is only a guess.)

Re: Interpolation in character class
by Anonymous Monk on Oct 02, 2003 at 18:03 UTC
    From original "Anonymous Monk" ... it appears that the $dle is interpolated within the character class and works as intended ! Is there anything to disuade me from the original construction ?

    It appears that variables (e.g. $dle) are interpolated within character classes  (e.g. [$dle])but not within hex character specifications (e.g \x{$dle}). Is there a reference source that makes this kind of information clear ? I have "Programming Perl", "Learning Perl", and "Perl Cookbook", but I didn't find it in those ... Thanks, Scott.