1
pattern = /domain\.com\/go\/(.*)3/i;

//alias always ends with "3"
url1 = "domain.com/go/firstname3";
url2 = "domain.com/go/secondname3?p=123";

console.log(url1.match(pattern)[1]); //firstname
console.log(url2.match(pattern)[1]); //secondname3?p=12

In both of examples I need return param without "3" ("firstname", "secondname"). It means I have to find first entry of char "3". First example works correctly

How should I change the pattern?

Thanks.

Alex Pavlov
  • 571
  • 1
  • 7
  • 24

2 Answers2

4

Use \w* instead of .*

pattern = /domain\.com\/go\/(\w*)3/i;

or

pattern = /domain\.com\/go\/(\w*)3\b/i;
Avinash Raj
  • 172,303
  • 28
  • 230
  • 274
1

This occurs because you are repeating the capturing group, and all language implementations preserve only the last capturing group. In other words, if there is a choice between capturing secondname and secondname3?p=12, Javascript will choose the last one even though both are equally valid. This answer explains the core of the problem.

The correct way to resolve such issues is to rewrite your regex group to make the parameter you want to retrieve unambiguous - usually this is done by changing occurrences of .* (note it is the . character here that is problematic) to something more appropriate, such as \w* in this case. You want to avoid repeating capturing groups. I will explain why \w does so.

Here \w represents the word metacharacter - it matches a-z, A-Z and 0-9 and nothing else. In this particular case, the regex can no longer match against secondname3?p=12 because it contains an =, which isn't allowed by \w. Hence why @Avinash Raj's solution works - even though the capturing group is repeated, there is only one real instance of the whole thing matching.

Community
  • 1
  • 1
Akshat Mahajan
  • 9,543
  • 4
  • 35
  • 44