in reply to Re: RegEx - match !foo followed by foo
in thread RegEx - match !foo followed by foo

Thanks Corion, but I don't think either merlyn's or your solution works... also I made one mistake in my examples:

foobar:helloworldgonk shouldn't match, because neither gonk nor @ can be found after no more than 5 preceding characters

Merlyn's solution fails (afaik) because it doesn't require the non-gonk to be followed by gonk (or @).

Your solution fails (afaik) because foobar:gonkgonk would return 'foobar:gonk' (and should return nothing).

To put it another way, if 'gonk' was a single character (say '£'), then I would do:

/foobar:[^£@]{1,5}[£@]/

Hope that makes it clearer

Tom Melly, tom@tomandlu.co.uk

Replies are listed 'Best First'.
Re^3: RegEx - match !foo followed by foo
by Corion (Patriarch) on Mar 16, 2006 at 13:36 UTC

    There are the edge cases of foobar:gonkogonk and foobar:ogonkgonk, which I've added to my below test cases. You need to decide if gonkogonk and ogonkgonk should be rejected or accepted. My solution rejects the first but accepts the second case.

    use strict; use Test::More tests => 6; sub ungonk { local $_ = $_[0]; if (/^(foobar:(?!gonk).{1,5})gonk$/) { return $1 } else { return undef }; }; is ungonk('foobar:hellogonk'), 'foobar:hello'; is ungonk('foobar:gonk'), undef; is ungonk('foobar:higonk'), 'foobar:hi'; is ungonk('foobar:helloworldgonk'), undef; is ungonk('foobar:gonkgonk'), undef; is ungonk('foobar:gonkogonk'), undef; is ungonk('foobar:ogonkgonk'), 'ogonk';

    Update: After reading your specification again, you don't want gonk to be found within the first five characters, but it must appear at the end. I think the below program does that, and rejects :ogonkgonk and :gonkogonk.

    use strict; use Test::More tests => 7; sub ungonk { local $_ = $_[0]; if (/^(foobar:(?:(?!gonk).){1,5})gonk$/) { return $1 } else { return undef }; }; is ungonk('foobar:hellogonk'), 'foobar:hello'; is ungonk('foobar:gonk'), undef; is ungonk('foobar:higonk'), 'foobar:hi'; is ungonk('foobar:helloworldgonk'), undef; is ungonk('foobar:gonkgonk'), undef; is ungonk('foobar:gonkogonk'), undef; is ungonk('foobar:ogonkgonk'), undef;

      Hmm, almost - and may be enough for me to work it out <thinks>...</thinks> Nope, still stuck

      foobar:ogonkgonk should return foobar:o

      Tom Melly, tom@tomandlu.co.uk

        The following passes the modified test suite.

        use strict; use Test::More tests => 7; sub ungonk { local $_ = $_[0]; if (/^(foobar:(?:(?!gonk).){1,5})gonk/) { return $1 } else { return undef }; }; is ungonk('foobar:hellogonk'), 'foobar:hello'; is ungonk('foobar:gonk'), undef; is ungonk('foobar:higonk'), 'foobar:hi'; is ungonk('foobar:helloworldgonk'), undef; is ungonk('foobar:gonkgonk'), undef; is ungonk('foobar:gonkogonk'), undef; is ungonk('foobar:ogonkgonk'), 'foobar:o';