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

what is the regular expression to find "abc" and "xyz" exist together in a give string irrespective of its case

i have tried using

$string =~ m/abc&xyz/i

$string =~ m/abc&&xyz/i

none of them work

please help me out

thanks

Farid

Replies are listed 'Best First'.
Re: Regular Expression
by dragonchild (Archbishop) on Feb 09, 2005 at 19:21 UTC
    if ($string =~ m/abc/i && $string =~ m/xyz/i) {

    Being right, does not endow the right to be rude; politeness costs nothing.
    Being unknowing, is not the same as being stupid.
    Expressing a contrary opinion, whether to the individual or the group, is more often a sign of deeper thought than of cantankerous belligerence.
    Do not mistake your goals as the only goals; your opinion as the only opinion; your confidence as correctness. Saying you know better is not the same as explaining you know better.

Re: Regular Expression
by ikegami (Patriarch) on Feb 09, 2005 at 19:33 UTC
    It can be done with a single regular expression ($string =~ /^(?=.*?abc).*?xyz/i), but you're better off using two (as dragonchild suggested) for readability.
Re: Regular Expression
by Enlil (Parson) on Feb 09, 2005 at 19:34 UTC
    You can do this a variety of ways, but here are three:
    $string =~ m/abc.*xyz|xyz.*abc/i $string =~ m/(?=.*abc)(?=.*xyz)/i; $string =~ /abc/i and $string =~ /xyz/i

    The ampersands inside the regular expression will be matched as ampersands and not used as logical operators.

    -enlil

      $string =~ m/(?=.*abc)(?=.*xyz)/i;

      That unanchored pattern is pathologically inficient. If the string does not match it will try and fail at every character position. Even with a relatively short strings this has a considerable effect.

      use Benchmark; my $string = 'x' x 100; timethese 1_000_000 => { unanchored => sub { $string =~ /(?=.*abc)(?=.*xyz)/i }, anchored => sub { $string =~ /^(?=.*abc)(?=.*xyz)/i }, };

      Benchmark: timing 1000000 iterations of anchored, unanchored...
      anchored: 1 wallclock secs ( 1.30 usr + 0.00 sys = 1.30 CPU) @ 768049.16/s (n=1000000)
      unanchored: 70 wallclock secs (70.12 usr + 0.00 sys = 70.12 CPU) @ 14261.06/s (n=1000000)

Re: Regular Expression
by TedPride (Priest) on Feb 09, 2005 at 19:30 UTC
    Or you can lowercase a copy of $string and use index calls, which is my personal choice if a lot of finds are required.
Re: Regular Expression
by gopalr (Priest) on Feb 11, 2005 at 06:44 UTC

    Hi

    & is a special character one. That's why it doesn't match. Use the following:

    if (($string=~m/abc/i && $string=~m/xyz/i)) { print "\nMatched"; }

    Or Simply use

    if ($string=~m#(abc).*?(xyz)#i) { print "\nfound"; }
Re: Regular Expression
by Roy Johnson (Monsignor) on Feb 09, 2005 at 21:33 UTC
    Um...nobody suggested
    (keys %{{map {$_=>1} /abc|xyz/gi}} == 2)
    I wonder why.

    Caution: Do not take internally.
      Perhaps because it would accept the text "abcABC" and reject the text "abcABCxyz"? Now, (keys %{{map {lc,1} /abc|xyz/gi}} == 2) would work...
        Touché.

        Caution: Contents may have been coded under pressure.

      The picture you have on your home node is quite apt for this type of response. Thanks :-)

Re: Regular Expression
by sh1tn (Priest) on Feb 09, 2005 at 21:00 UTC
    In case we search not only in the beginning:
    use Benchmark; use strict; my $string = 'x' x 100; my $regex = qr{(?:abc|xyz)}; timethese 1_000_000 => { unanchored => sub { $string =~ /$regex/i }, anchored => sub { $string =~ /^(?=.*abc)(?=.*xyz)/i }, }; __END__ Benchmark: timing 1000000 iterations of anchored, unanchored... anchored: 1 wallclock secs ( 1.55 usr + -0.01 sys = 1.53 CPU) @ 65 +2741.51/s (n=1000000) unanchored: 19 wallclock secs (19.37 usr + 0.00 sys = 19.37 CPU) @ 51 +615.57/s (n=1000000)