0

I'm trying to write a regex route in zend (1.11) that matches urls ending in /foo but not if they start with /bar e.g.

/foo - match
/any/words/foo - match

/any/words - no match (doesn't end in /foo)
/any/words/barfoo - no match (doesn't end in /foo)
/bar/foo - no match (starts with /bar)
/bar/any/words/foo - no match (starts with /bar)

my regext route looks like this:

'^foo$|^(?!/bar/).+/foo$'

But I find it matches anything ending in /foo, even if it starts with /bar.

xanld
  • 977
  • 1
  • 11
  • 22

2 Answers2

1

You Need a Negative Lookahead

Lucky for you, I have one in my pocket. Try this:

^(?!/bar).*/foo$

See what matches in the demo.

  • The ^ anchor asserts that we are at the beginning of the string
  • The negative lookahead (?!/bar) asserts that what follows is not /bar
  • .* matches any characters (dot is any character except newlines, the star repeats it zero or more times)
  • /foo matches /foo
  • The $ anchor asserts that we are at the end of the string

Reference

zx81
  • 41,100
  • 9
  • 89
  • 105
  • Thanks for the amazing speedy response. However it doesn't seem to work as a zend regex route. I'm fairly sure my regex does the job (will test in http://regex101.com/), but in the zend regex route context, it still matches urls starting with /bar. I'm doing more tests now... – xanld Jun 26 '14 at 04:43
  • Aha - I think I may have found it. (?!bar).*/foo - the leading slash is not passed as part of the string to match. More tests and confirmation to follow! – xanld Jun 26 '14 at 04:46
  • Mmm, the regex is correct, why would it not work? Here are two explanations I can think of: (i) no support for lookahead, or (ii) the regex uses a `/` delimiter, so the `/` inside would have to be escaped – zx81 Jun 26 '14 at 04:47
  • Looks like our messages crossed paths... What you found is consistent with my idea #2... In which case (i) change the delimiter if possible, or (ii) escape the slashes in the regex: `^(?!\/bar).*\/foo$` (same as in regex101) – zx81 Jun 26 '14 at 04:48
0

Final solution:

'^foo$|^(?!bar).*/foo$'

Explanation The regex was a red-herring, this was more of a zend problem. My problem was that the url string that is passed to Zend doesn't contain a leading slash, so I was testing regex against the wrong input. So in my solution I need to look for '^foo$' to match '/foo' OR '^(?!bar).*/foo$' to match '/any/words/foo' excluding '/bar/any/words/foo'.

Special thanks however to @zx81 for an amazingly fast and detailed response, and helping un-block my thinking. I'd recommend reading his response above for reference.

xanld
  • 977
  • 1
  • 11
  • 22