Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

Programmatically forcing a regexp to fail

by suaveant (Parson)
on Oct 31, 2007 at 20:34 UTC ( #648360=perlquestion: print w/ replies, xml ) Need Help??
suaveant has asked for the wisdom of the Perl Monks concerning the following question:

It seems to me like I saw some way... maybe using (?{ }) or (??{ }) that you could force a failure of the regexp (or current branch). But I can't for the life of me remember what it was.

A completely contrived example would be only matching numbers divisible by three, where you would do something like /(\d+)(?{ !($^N%3) })/... though this of course doesn't actually work.

Can anyone help, or am I remembering things that aren't there?

                - Ant
                - Some of my best work - (1 2 3)

Comment on Programmatically forcing a regexp to fail
Select or Download Code
Re: Programmatically forcing a regexp to fail
by mwah (Hermit) on Oct 31, 2007 at 20:56 UTC
    that you could force a failure of the regexp

    It's probably the 'empty negative lookahead' (?!) :

    ... my @nums = 1 .. 30; my $reg = qr{^(\d+)$ (??{ $1 % 3 ? '(?!)' : '' })}x; print join ',', grep /$reg/, @nums; ...

    This is documented eg. in Jeff Pinyan's work (also here on perlmonks).

    Correction 1: Added bounds "^ $" to \d+ to prevent backtracking in the above example.

    Correction 2: backtracking can be prevented by the atomic group (?>...):

    ... my $reg = qr{ ^((?>\d+)) (??{ !!($1 % 3) and '(?!)' }) }x; ...

    Regards

    mwa

      I don't think that's what I had seen before but it works. Thanks! :)

                      - Ant
                      - Some of my best work - (1 2 3)

Re: Programmatically forcing a regexp to fail
by ikegami (Pope) on Nov 05, 2007 at 15:57 UTC
    /^(\d+)$ (?(?{ $^N % 3) })(?!))/x

    works, but

    /^(\d+)$/ && ($1 % 3 == 0)

    is easier to read and maintain.

    Note that in 5.10, you'll be able to use (*FAIL) instead of (?!), but you're better off with (?!) for backwards compatibility.
    Note that $^N made its first appearance in rather recent 5.8, so you're better off using $1 for backwards compatibility.

Re: Programmatically forcing a regexp to fail
by Yary (Scribe) on Jul 11, 2011 at 19:27 UTC

    I have a similar question, hope it's OK to add on to this old thread.

    If I want to create a regular expression that always fails, and fails quickly, will qr/(*FAIL)/ be the best way? Or will it backtrack over each character? Would qr/^(*FAIL)/ be better?

    I'm asking because I'm going through many large log files, where I look for any string that matches a "begin", and build up a "end" regexp... and then remove pieces as I come across "ends", which might then make the end regexp back to null. The null case could be checked like:

    if ($there_is_an_ending && /$end_pattern/) ...

    but it seems cleaner to set $end_pattern=qr/(*FAIL)/ (not use $there_is_an_ending at all)- if that is indeed efficient.

    Maybe time for me to learn to use the cool regular expression debugger and see what happens under the hood!

    EDIT

    Thanks to help from Somni and Tanktalus in the chatterbox-

    $  perl -Mre=debug -E '"foo" =~ /(*FAIL)/'
    Compiling REx "(*FAIL)"
    Final program:
       1: OPFAIL (2)
       2: END (0)
    minlen 0
    Matching REx "(*FAIL)" against "foo"
       0 <> <foo>                |  1:OPFAIL(2)
                                      failed...
       1 <f> <oo>                |  1:OPFAIL(2)
                                      failed...
       2 <fo> <o>                |  1:OPFAIL(2)
                                      failed...
       3 <foo> <>                |  1:OPFAIL(2)
                                      failed...
    Match failed
    

    vs

    $  perl -Mre=debug -E '"foo" =~ /^(*FAIL)/'
    Compiling REx "^(*FAIL)"
    Final program:
       1: BOL (2)
       2: OPFAIL (3)
       3: END (0)
    anchored(BOL) minlen 0
    Matching REx "^(*FAIL)" against "foo"
       0 <> <foo>                |  1:BOL(2)
       0 <> <foo>                |  2:OPFAIL(3)
                                      failed...
    Match failed
    

    and the winner is

    /^(*FAIL)/

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others wandering the Monastery: (7)
As of 2014-12-21 15:23 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    Is guessing a good strategy for surviving in the IT business?





    Results (106 votes), past polls