user1491636
user1491636

Reputation: 2436

Regex With Negative Lookahead For Word

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

Answers (2)

anubhava
anubhava

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 Demo

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

Ryszard Czech
Ryszard Czech

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

Related Questions