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

I'm looking for the shortest way of doing this... my $var="xyz"; if (($var =~ /x/) && ($var =~ /y/) && ($var =~ /z/)) {print "all in m8\n"} so that I can just add remove space separated patterns Thank you in anticipation.

Replies are listed 'Best First'.
Re: ensure ALL patterns in string
by davido (Cardinal) on Jan 22, 2016 at 21:04 UTC

    print "all\n" if 3 == grep {$var =~ m/$_/} qw(x y z);

    ...or...

    use List::Util 'all'; print "all\n" if all {$var =~ m/$_/} qw(x y z);

    If the patterns contain spaces use a different quoting mechanism.


    Dave

      Thanks Dave...those look well short and sweet!
Re: ensure ALL patterns in string
by AnomalousMonk (Archbishop) on Jan 22, 2016 at 20:58 UTC

    From the standpoint of clarity and maintainability, I'm not sure what you have now | in the OP isn't really best. But if you want an "all in one regex" solution, try something like:

    c:\@Work\Perl\monks>perl -wMstrict -le "my $s = 'aZaXaYa'; ;; print 'all there' if $s =~ m{ \A (?= .*? X) (?= .*? Y) (?= .*? Z) }xm +s; " all there
    See Look-Around Assertions in perlre; the Looking ahead and looking behind section in perlretut.

    ... so that I can just add remove space separated patterns ...

    I don't understand what this means.


    Give a man a fish:  <%-{-{-{-<

      re clarity I probably agree re not understanding... I mean the x y and z on the right in Dave's solution print "all\n" if 3 == grep {$var =~ m/$_/} qw(x y z); ie if you want another word you just pop it in after z...without typing anything else. Thank's for your help
Re: ensure ALL patterns in string
by Mr. Muskrat (Canon) on Jan 22, 2016 at 20:59 UTC

    Why do you want the shortest? Here's one way to do it.

    #!/bin/env perl use strict; use warnings; use List::Util qw(all); my $var = 'xyz'; if ( all { $var =~ $_ } ( qr/x/, qr/y/, qr/z/ ) ) { print "all in m8\n"; }
      >Why do you want the shortest I find short more comprehensible in general...just the way I'm wired I guess. Irresponsible thank you for your solution.

        While the shortest may generally be the easiest to understand in most cases, that might not always be true. The motto of Perl is "There Is More Than One Way To Do It" (TIMTOWTDI). Quite often the SHORTEST way to do something is done in a rather obscure way. Perl is especially good for playing Golf with the code - where the winner is the one who uses the fewest characters to do a task. See Perl Golf 101's examples at the bottom. I think many of them are easier to understand before being shortened.

        I love coming to this site because I learn something new here each day. There are a lot of pro level Perl Golfers on this site, and it amazing just watching them driving or putting on the greens.

Re: ensure ALL patterns in string
by Laurent_R (Canon) on Jan 22, 2016 at 22:07 UTC
    { local $_ = "z r x r t y"; print "all\n" if /x/ and /y/ and /z/; }
      Thank you Laurent.
Re: ensure ALL patterns in string
by jeffa (Bishop) on Jan 22, 2016 at 20:55 UTC

    There are few ways you can condense this, here is one:

    print "all in m8\n" if $var =~ /.*x.*y.*z.*/;
    As in:
    for (<DATA>) { chomp; print "$_: all in m8\n" if /.*x.*y.*z.*/; } __DATA__ foo xoo fyo foz xyo fyz xyz

    UPDATE: Nope, that won't capture 'zyx' (and .* is awful) ... you could mangle the regex more or ... just use a lookup table:

    my %hash = ( x => 1, y => 1, z => 1 ); for (<DATA>) { chomp; my $in = 0; my %hash = ( x => 1, y => 1, z => 1 ); for my $x (split //, $_) { delete $hash{$x} and $in++; } print "$_: all in m8\n" if $in == 3; }
    That works, but perhaps List::Util is the way to go ... yes, i think so. :)

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    B--B--B--B--B--B--B--B--
    H---H---H---H---H---H---
    (the triplet paradiddle with high-hat)
    
      Thanks for the alternatives. I'm quite new to Perl and it's very educational to see the various methods. Thank you.
Re: ensure ALL patterns in string
by kcott (Archbishop) on Jan 25, 2016 at 10:39 UTC

    G'day previous,

    Change

    if (($var =~ /x/) && ($var =~ /y/) && ($var =~ /z/)) {...

    to

    if (grep { /x/ && /y/ && /z/ } $var) {...

    My test:

    #!/usr/bin/env perl -l use strict; use warnings; my @test_strings = qw{ ooo xoo oyo ooz xyo xoz oyz xyz oxo ooy zoo oxy zxo zoy zxy oox yoo ozo yox ozx yzo yzx oxyz oxoyz oxoyoz oxoyozo }; for my $var (@test_strings) { if (grep { /x/ && /y/ && /z/ } $var) { print "All in: $var"; } }

    Output:

    All in: xyz All in: zxy All in: yzx All in: oxyz All in: oxoyz All in: oxoyoz All in: oxoyozo

    — Ken

Re: ensure ALL patterns in string
by toolic (Bishop) on Jan 22, 2016 at 20:53 UTC
    Misread the question.

    Equivalent code using a character class:

    my $var = "xyz"; if ($var =~ /[xyz]/) { print "all in m8\n" }
      No problem! Thanks for your willingness to help.