3

I have - let say - example.com website and there I have account page. It may have GET parameters, which is also considered part of account page. It also may have URL fragment. If it's home.html fragment - it is still the account page. And if another fragment - then it's a different sub-page of the account page.

So - I need a RegEx (JS) to match this case. This is what I managed to build so far:

example.com\/account\/(|.*\#home\.html|(\?(?!.*#.*)))$

https://regex101.com/r/ihjCIg/1

The first 4 are the cases I need. And as you see - the second row is not matched by my RegEx.

What am I missing here?

Matt Ellen
  • 11,268
  • 4
  • 68
  • 90
pesho hristov
  • 1,946
  • 1
  • 25
  • 43
  • You may be interested in the `window.location` object where you can check `pathname` and `hash` without worrying about the parameters. However, the parameters are available in `search` if you need them. – MonkeyZeus Aug 27 '19 at 11:39
  • Do you want to exclude the last two cases? – Matt Ellen Aug 27 '19 at 11:40
  • This is happening in a 3rd party tool, otherwise I would make it just check the pathname and the hash and will handle all the cases I want :) – pesho hristov Aug 27 '19 at 11:52
  • Are you looking for something like this [`Regex`](https://regex101.com/r/ihjCIg/1) – Code Maniac Aug 27 '19 at 11:58

3 Answers3

3

You could create 2 optional groups, 1 to optionally match ? and matching any char except # and another optional group matching #home.html

Note to escape the dot to match it literally.

^example\.com\/account\/(?:\?[^#\r\n]*)?(?:#home\.html)?$
  • ^ Start of string
  • example\.com\/account\/ Match start
  • (?: Non capturing group
    • \?[^#\r\n]* Match ? and 0+ times any char except # or a newline
  • )? Close group and make it optional
  • (?: Non capturing group
    • #home\.html Match #home.html
  • )? Close group and make it optional
  • $

Regex demo

let pattern = /^example\.com\/account\/(?:\?[^#\r\n]*)?(?:#home\.html)?$/;
[
  "example.com/account/",
  "example.com/account/?brand=mine",
  "example.com/account/#home.html",
  "example.com/account/?brand=mine#home.html",
  "example.com/account/#other.html",
  "example.com/account/?brand=mine#other.html"
].forEach(url => console.log(url + " --> " + pattern.test(url)));
The fourth bird
  • 154,723
  • 16
  • 55
  • 70
  • 1
    Not pretty sure `xyz.com/?#123` is valid url schema or not, if not than we probably need to have `*` quantifier replaced with `+` and also consider having something like `queryName=queryValue` structure, anyways +1 – Code Maniac Aug 27 '19 at 12:14
  • 1
    @CodeManiac I get your point. In this case it is for a broad match only and it could potentially match more questionable url formats. In that case I think a specific set of allowed characters by the OP would be better. – The fourth bird Aug 27 '19 at 12:20
  • 1
    Yeah totally agree with you, regex can handle only the specified one's only, to be more generic we should always prefer the URL api :) – Code Maniac Aug 27 '19 at 12:23
1

Third alternative in your group has a negative look ahead which ensures it rejects any text that contains a # but you haven't specifically mentioned anything that should match rest of the content till end of line. Check this updated regex demo,

https://regex101.com/r/ihjCIg/3

If you notice, I have escaped your first dot just before com and have added .* after the negative look ahead part so it matches your second sample.

Silvanas
  • 613
  • 3
  • 11
  • But I have `.*` right after the `#` ... I thought this is handling the rest characters, til the end of the URL ... – pesho hristov Aug 27 '19 at 12:03
  • 1
    @peshohristov: Ok, that `.*` after `#` was just needed to be taken out of negative lookahead and it would work like you expected. Check this updated link https://regex101.com/r/ihjCIg/6 – Silvanas Aug 27 '19 at 12:44
  • 1
    Thanks for the explanation, that was useful :) – pesho hristov Aug 27 '19 at 13:33
1
example\.com\/account\/((\??[^#\r\n]+)?(#?home\.html)?)?$

This matches your first four strings

example.com/account/
example.com/account/?brand=mine
example.com/account/#home.html
example.com/account/?brand=mine#home.html

and excludes your last two

example.com/account/#other.html
example.com/account/?brand=mine#other.html
Matt Ellen
  • 11,268
  • 4
  • 68
  • 90