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

sending a command to my storage server and parsing the response. i'm looking for any line in the FH that have the word SATA and has N/A written twice. Here's my RE that looks for a single N/A && SATA... any ideas? if ( $_ =~ /\bsata\b/i && /\bN\/A\b*\bN\/A\b/i )

Replies are listed 'Best First'.
Re: Looking for N/A twice
by FunkyMonk (Bishop) on Oct 21, 2007 at 18:42 UTC
    What about
    $_ = "gjhgjhgjg sata kjhkhkjhkjhkj N/A khkjhkhkhkj N/A"; print "yeah" if m{\bsata\b}i && m{\bN/A\b.*\bN/A\b}i

Re: Looking for N/A twice
by polettix (Vicar) on Oct 21, 2007 at 18:53 UTC
    You don't need to explicitly use $_ in a pattern match, and you can use a single regexp (together with FunkyMonk's advice):
    if (m{ \bsata\b .*? \bN/A\b .*? \bN/A\b }ix) { ... }
    I added the x modifier just to separate the different parts a bit and make it a little more readable (see perlre for more details).

    Flavio
    perl -ple'$_=reverse' <<<ti.xittelop@oivalf

    Io ho capito... ma tu che hai detto?
      You can use a single regex regardless of order if you use look-ahead assertions.

      $ perl -le ' > $_ = "gjhgjhgjg sata kjhkhkjhkjhkj N/A khkjhkhkhkj N/A"; > print q{ok} if m{(?ix) (?=.*\bn/a\b.+\bn/a\b) (?=.*\bsata\b)};' ok $

      Cheers,

      JohnGG

        This struck me like a thunder:
        m{(?ix) (?=.*\bn/a\b.+\bn/a\b) (?=.*\bsata\b)}
        I thought that the span of application of (?ix) was the stuff inside the two parentheses (just like a contracted form of (?ix:)), but your regex clearly contradicts this. So I turned to the manpage and... it's there, nicely documented! I love this language.

        Flavio
        perl -ple'$_=reverse' <<<ti.xittelop@oivalf

        Io ho capito... ma tu che hai detto?
      The OP didn't state the order that the three phrases will appear. Your regexp won't match N/A sata N/A, for example.

      Only neo1491 can say if this is what s?he wants.

        You're right, after re-reading it, I have to admit that I was fooled... by your example :) Good catch anyway, thanks.

        Flavio
        perl -ple'$_=reverse' <<<ti.xittelop@oivalf

        Io ho capito... ma tu che hai detto?
Re: Looking for N/A twice
by ambrus (Abbot) on Oct 21, 2007 at 20:27 UTC

    I recommend matching the same regexp twice: if (/\bsata\b/i && /\bN\/A\b/ig && /\bN\/A\b/ig)

      Magic works :)
      use re 'debug'; $_ = "one sata two N/A three N/A"; die if (/\bsata\b/i && /\bN\/A\b/ig && /\bN\/A\b/ig) ; __END__ Compiling REx `\bsata\b' size 5 Got 44 bytes for offset annotations. first at 1 1: BOUND(2) 2: EXACTF <sata>(4) 4: BOUND(5) 5: END(0) stclass `BOUND' minlen 4 Offsets: [5] 1[2] 3[4] 0[0] 7[2] 9[0] Compiling REx `\bN/A\b' size 5 Got 44 bytes for offset annotations. first at 1 1: BOUND(2) 2: EXACTF <N/A>(4) 4: BOUND(5) 5: END(0) stclass `BOUND' minlen 3 Offsets: [5] 1[2] 3[3] 0[0] 6[2] 8[0] Compiling REx `\bN/A\b' size 5 Got 44 bytes for offset annotations. first at 1 1: BOUND(2) 2: EXACTF <N/A>(4) 4: BOUND(5) 5: END(0) stclass `BOUND' minlen 3 Offsets: [5] 1[2] 3[3] 0[0] 6[2] 8[0] Matching REx `\bsata\b' against `one sata two N/A three N/A' Matching stclass `BOUND' against `one sata two N/A three ' Setting an EVAL scope, savestack=3 0 <> <one sata two> | 1: BOUND 0 <> <one sata two> | 2: EXACTF <sata> failed... Setting an EVAL scope, savestack=3 3 <one> < sata two> | 1: BOUND 3 <one> < sata two> | 2: EXACTF <sata> failed... Setting an EVAL scope, savestack=3 4 <one > <sata two> | 1: BOUND 4 <one > <sata two> | 2: EXACTF <sata> 8 < sata> < two N/> | 4: BOUND 8 < sata> < two N/> | 5: END Match successful! Matching REx `\bN/A\b' against `one sata two N/A three N/A' Matching stclass `BOUND' against `one sata two N/A three N' Setting an EVAL scope, savestack=3 0 <> <one sata two> | 1: BOUND 0 <> <one sata two> | 2: EXACTF <N/A> failed... Setting an EVAL scope, savestack=3 3 <one> < sata two> | 1: BOUND 3 <one> < sata two> | 2: EXACTF <N/A> failed... Setting an EVAL scope, savestack=3 4 <one > <sata two> | 1: BOUND 4 <one > <sata two> | 2: EXACTF <N/A> failed... Setting an EVAL scope, savestack=3 8 < sata> < two N/> | 1: BOUND 8 < sata> < two N/> | 2: EXACTF <N/A> failed... Setting an EVAL scope, savestack=3 9 <sata > <two N/A> | 1: BOUND 9 <sata > <two N/A> | 2: EXACTF <N/A> failed... Setting an EVAL scope, savestack=3 12 <a two> < N/A th> | 1: BOUND 12 <a two> < N/A th> | 2: EXACTF <N/A> failed... Setting an EVAL scope, savestack=3 13 < two > <N/A thr> | 1: BOUND 13 < two > <N/A thr> | 2: EXACTF <N/A> 16 <o N/A> < three > | 4: BOUND 16 <o N/A> < three > | 5: END Match successful! Matching REx `\bN/A\b' against ` three N/A' Matching stclass `BOUND' against ` three N' Setting an EVAL scope, savestack=3 16 <o N/A> < three > | 1: BOUND 16 <o N/A> < three > | 2: EXACTF <N/A> failed... Setting an EVAL scope, savestack=3 17 < N/A > <three N> | 1: BOUND 17 < N/A > <three N> | 2: EXACTF <N/A> failed... Setting an EVAL scope, savestack=3 22 </A three> < N/A> | 1: BOUND 22 </A three> < N/A> | 2: EXACTF <N/A> failed... Setting an EVAL scope, savestack=3 23 </A three > <N/A> | 1: BOUND 23 </A three > <N/A> | 2: EXACTF <N/A> 26 </A three N/A> <> | 4: BOUND 26 </A three N/A> <> | 5: END Match successful! Died at same.regex.twice.pl line 5. Freeing REx: `"\\bsata\\b"' Freeing REx: `"\\bN/A\\b"' Freeing REx: `"\\bN/A\\b"'
Re: Looking for N/A twice
by neo1491 (Beadle) on Oct 21, 2007 at 18:58 UTC
    sweet... this actually worked. THANKS! if ( $_ =~ /\bsata\b/i && /\bN\/A\b*\bN\/A\b/i )
Re: Looking for N/A twice
by Cody Pendant (Prior) on Oct 22, 2007 at 04:59 UTC
    Off-topic, but I realised that you could search for two or more occurrences of a substring in a string with nested index() calls like this:
    $str = 'N/A N/A blah blah blah SATA N/A blah blah N/A'; $substr = 'N/A'; if (index($str,$substr, index($str,$substr)+1 ) ) { print "two or more occurrences of '$substr' in '$str'" }
    which is probably way faster than any RegEx method.


    Nobody says perl looks like line-noise any more
    kids today don't know what line-noise IS ...

      No way. index($str,$substr, index($str,$substr)+1 practically always returns true, even if $str has $substr only once or not at all. I don't think it's way faster than regexen either.