Reputation: 2436
Using a PCRE flavour, I'm trying to come up with a regex that will match a URL as long as it does not contain /foo
after the /songs/{id}
/songs/902 => Match
/songs/902/ => Match
/songs/902/foo => No Match
/songs/902/foo/201/bar => No Match
/songs/902/bar => Match
This is what I have so far ^\/songs\/.+(?!\/foo).*$
but it seems to match all the given examples.
Upvotes: 1
Views: 151
Reputation: 784918
You're using /songs/.+(?!\/foo)
where negative lookahead is applied after greedy .+
, that after /songs/
, will just match everything including /foo
till end and then it will satisfies lookahead assertion. You need to apply lookahead assertion just after matching /songs/
or /songs/<digits>
.
You may use this regex in php
with a negative lookahead:
~/songs/\d+(?!.*/foo\b)~
RegEx Details:
/songs/\d+
: Match /songs/
followed by 1+ digits(?!.*/foo\b)
: Negative lookahead to fail the match if we have /foo
ahead of the current position.Code:
$re = '~/songs/\d+(?!.*/foo\b)~';
preg_match_all($re, $input, $matches);
// Print the match result
var_dump($matches[0]);
Upvotes: 1
Reputation: 18611
Use
^\/songs\/(?!.*\/foo).+
See proof. The ^\/songs\/
locates /songs/
at the start, then (?!.*\/foo)
check if /foo
is present later in the string, and .+
matches what remains.
Upvotes: 1