Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

Character class in an array

by nikto (Initiate)
on Sep 17, 2002 at 17:08 UTC ( [id://198557]=perlquestion: print w/replies, xml ) Need Help??

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

Hello. I have an array of characters that I would like to be able to pattern match against. I've written the following code:
@a = ( 'a', 'x', 'z' ); # simplified array while(<>) { print if(/^[@a]{3}$/); }
This works well, except that it also accepts space(' ') as a valid character. I've also tried to use join ('', @a) but it gives the same results. Can anyone explain to me why this happens? Thanks.

Replies are listed 'Best First'.
Re: Character class in an array
by dws (Chancellor) on Sep 17, 2002 at 17:21 UTC
    This works well, except that it also accepts space(' ') as a valid character.

    This is because of array interpolation, which uses the contents of $" to separate array elements when joining them together. You can use this to your advantage by doing something like

    @a = ( 'a', 'x', 'z' ); # simplified array while(<>) { local $" = ""; print if(/^[@a]{3}$/); }
    Note that this re-localizes $" within a loop, which isn't the most effecient approach, but then again you might not notice the performance difference without a microsocope.

Re: Character class in an array
by RMGir (Prior) on Sep 17, 2002 at 17:37 UTC
    Others have explained that $" is the source of your problem.

    However, there are other problems with what you're doing.

    You're repeating that interpolation on every trip through the loop, when you could be using qr// to compile your regex once and then forget about it.

    Here are some comparisons of a few of the other solutions mentioned in this thread, along with one where the regex is pre-built with qr//. These results are with 5.6.1 on cygwin; YMMV.

    $ perl testLocal.pl Benchmark: running localWhile, localWhileQR, whileLocal, each for at l +east 3 CPU seconds... localWhile: 4 wallclock secs ( 3.02 usr + 0.00 sys = 0.02 CPU) @ 28 +894.20/s (n=87116) localWhileQR: 4 wallclock secs ( 3.17 usr + 0.01 sys = 3.18 CPU) @ +45765.70/s (n=145718) whileLocal: 4 wallclock secs ( 3.09 usr + 0.00 sys = 3.09 CPU) @ 20 +884.62/s (n=64617) Rate whileLocal localWhile localWhileQR whileLocal 20885/s -- -28% -54% localWhile 28894/s 38% -- -37% localWhileQR 45766/s 119% 58% --
    The benchmark code is here:
    --
    Mike
      You're repeating that interpolation on every trip through the loop, when you could be using qr// to compile your regex once and then forget about it.

      The /o flag on the regex will also work without requiring him to create a regex scalar with qr//.

        And it may not work always. See 'o' modifier clarification needed

        ____________________________________________________
        ** The Third rule of perl club is a statement of fact: pod is sexy.

        But will fail if the regex is used multiple times with varying array contents.

        Makeshifts last the longest.

Re: Character class in an array
by Nemp (Pilgrim) on Sep 17, 2002 at 17:18 UTC
    Hi,

    If I understand your problem correctly it is being caused by the default list seperator $" which is set to a space as default. This is used to seperate array values interpolated into a string hence your regex is also allowing spaces in the character class, which I believe is becoming [a x z] in your example above.

    I tried code similar to yours with the following line added before the interpolation and it worked fine for me.

    $" = '';

    HTH,
    Neil

    Note: all opinion in this post is from a newbie, "wow I think I understood something!" point of view :)
Re: Character class in an array
by fglock (Vicar) on Sep 17, 2002 at 17:13 UTC

    you are getting  [a x z] instead of  [axz] when you say  [@a]

    Are you sure your  join used an empty string? That is,  '' instead of  ' '

    Try:

    $tmp = join('',@a); print if /^[$tmp]{3}$/;
Re: Character class in an array
by japhy (Canon) on Sep 17, 2002 at 17:32 UTC
    You can localize $" to the empty string, or just use a scalar instead:
    my @a = qw( a x z ); { local $" = ""; while (<>) { print if /^[@a]{3}$/; # /o might be good, too } }
    or
    my @a = qw( a x z ); my $re = join '', @a; while (<>) { print if /^$re$/; # again, /o might help }

    _____________________________________________________
    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:??;

Re: Character class in an array
by BrowserUk (Patriarch) on Sep 17, 2002 at 17:20 UTC

    Update: nemp's post above this got it first and got it right.

    It should be $" not $, Below corrected.

    @a = ( 'a', 'x', 'z' ); # simplified array { # restrict scope of changes to $, local $"=''; # change from default space to null string while(<>) { print if(/^[@a]{3}$/); } }

    Cor! Like yer ring! ... HALO dammit! ... 'Ave it yer way! Hal-lo, Mister la-de-da. ... Like yer ring!
Re: Character class in an array
by zigdon (Deacon) on Sep 17, 2002 at 17:16 UTC
    When I tried to use this code with the join('', @a) everything worked ok?
    I think that what's happening here is that @a is getting interpolated as if in a double quoted string - with $" as as the seperator, which is space by default. The fact that it works with the join seems to agree with this theory.

    -- Dan

Re: Character class in an array
by Aristotle (Chancellor) on Sep 17, 2002 at 21:23 UTC
    Another option over using $" is to inline the join in your regex.
    my @a = ( 'a', 'x', 'z' ); my $match = qr/^[@{[ join '', @a ]}]{3}$/; while(<>) { print if /$match/; }
    You can embed Perl inside any literal strings in this fashion.

    Makeshifts last the longest.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://198557]
Approved by earthboundmisfit
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others sharing their wisdom with the Monastery: (3)
As of 2024-04-15 16:45 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found