Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
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 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 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 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 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 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 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 perusing the Monastery: (4)
As of 2024-04-19 02:56 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found