Reputation: 1
At Regex to match url segment only if not preceded by specific parent segment
given the input
http://example.com/my-slug
or http://example.com/my-slug/
the requirement is to match
"my-slug"
but not to match
"my-slug"
if preceded by
"news-events"
Was able to match "/my-slug"
or "/my-slug/"
by using RegExp lookbehind assertions at Chromium with --harmony
flag set with RegExp
// why is the `\/` necessary following lookbehind?
let re = /(?<!news-events)\/[^/]+(?=\/$|$)/;
let sources = [
"http://example.com/my-slug"
, "http://example.com/my-slug/"
, "http://example.com/news-events/my-slug"
];
for (let src of sources) {
console.log(src.match(re))
}
however, when trying to precisely match "my-slug"
without preceding "/"
character by escaping the trailing "/"
at news-event/
the RegExp
does not return same match, where the match for "http://example.com/news-events/my-slug"
is "y-slug"
when the expected result is null
let re = /(?<!news-events\/)[^/]+(?=\/$|$)/;
let sources = [
"http://example.com/my-slug"
, "http://example.com/my-slug/"
, "http://example.com/news-events/my-slug"
];
for (let src of sources) {
console.log(src.match(re))
}
Questions:
Why is the escaped "/"
character not included as part of the RegExp
lookbehind negation assertion?
How to properly escape characters or otherwise adjust the RegExp
lookbehind assertion to negate the full string "news-events/"
and return the expected result "my-slug"
without needing to include \/
before portion of string which should be matched?
Upvotes: 1
Views: 656
Reputation: 224962
Since this bit of the regular expression:
[^/]+(?=\/$|$)
matches the text y-slug
(y-slug
is multiple non-slash characters, optionally followed by a slash, followed by the end of the string), and y-slug
is not preceded by news-events/
, it’s a valid match. Since my-slug
doesn’t match, it’s also the first valid match, so it’s the match that is returned.
You could add a second, positive lookbehind to indicate that any match must be a complete segment.
let re = /(?<!news-events\/)(?<=\/)[^/]+(?=\/$|$)/;
let sources = [
"http://example.com/my-slug"
, "http://example.com/my-slug/"
, "http://example.com/news-events/my-slug"
];
for (let src of sources) {
console.log(src.match(re))
}
Upvotes: 1