Splitting string into matching and non-matching groups in javascript - javascript

I am trying to split the string into an array of strings those matching a regular expression and those that don't:
string = "Lazy {{some_animal}} jumps over.."
# do some magic with regex /({{\s?[\w]+\s?}})/g and its negation
array = ["Lazy ", "{{some_animal}}", " jumps over.."]
Best performant way to do that in javascript?

You can use String match for that
The regex below simply matches anything that's not a mustach, optionally surrounded by mustaches.
Example snippet:
var str = "Lazy {{some_animal}} jumps over..";
const pattern = /\{*[^{}]+\}*/g;
var array = str.match(pattern);
console.log(str);
console.log(pattern);
console.log(array);
But to make it more precise, the regex pattern becomes a bit more complicated.
The regex below matches:
"what you want"
(a word between 2 mustaches on each side)
OR "what you don't want followed by what you want"
(using lazy matching and positive lookahead)
OR "what remains"
var str = "Lazy {{some_animal}} jumps over..";
const pattern = /\{\{\w+\}\}|.+?(?=\{\{\w+\}\})|.+/g;
var array = str.match(pattern);
console.log(str);
console.log(pattern);
console.log(array);
And last but not least, the evil SM method.
Split AND Match on the same regex. And concatinate them into a single array.
The downside of this method is that the order is not preserved.
var str = "Lazy {{some_animal}} jumps over..";
const pattern = /\{\{\w+\}\}/g;
var what_you_want = str.match(pattern);
var what_you_dont_want = str.split(pattern);
var array = what_you_want.concat(what_you_dont_want);
console.log(str);
console.log(pattern);
console.log(array);

I'm fairly sure a simple exec loop is going to be your best option:
function getSegments(rex, str) {
var segments = [];
var lastIndex = 0;
var match;
rex.lastIndex = 0; // In case there's a dangling previous search
while (match = rex.exec(str)) {
if (match.index > lastIndex) {
segments.push(str.substring(lastIndex, match.index));
}
segments.push(match[0]);
lastIndex = match.index + match[0].length;
}
if (lastIndex < str.length) {
segments.push(str.substring(lastIndex));
}
return segments;
}
var rex = /{{\s?[\w]+\s?}}/g;
var string = "Lazy {{some_animal}} jumps over..";
console.log(getSegments(/{{\s?[\w]+\s?}}/g, string));
Note I removed the capture group; it's not needed for this sort of solution.

Related

JS Regex - non-capturing group not working [duplicate]

I want to match a portion of a string using a regular expression and then access that parenthesized substring:
var myString = "something format_abc"; // I want "abc"
var arr = /(?:^|\s)format_(.*?)(?:\s|$)/.exec(myString);
console.log(arr); // Prints: [" format_abc", "abc"] .. so far so good.
console.log(arr[1]); // Prints: undefined (???)
console.log(arr[0]); // Prints: format_undefined (!!!)
What am I doing wrong?
I've discovered that there was nothing wrong with the regular expression code above: the actual string which I was testing against was this:
"date format_%A"
Reporting that "%A" is undefined seems a very strange behaviour, but it is not directly related to this question, so I've opened a new one, Why is a matched substring returning "undefined" in JavaScript?.
The issue was that console.log takes its parameters like a printf statement, and since the string I was logging ("%A") had a special value, it was trying to find the value of the next parameter.
Update: 2019-09-10
The old way to iterate over multiple matches was not very intuitive. This lead to the proposal of the String.prototype.matchAll method. This new method is in the ECMAScript 2020 specification. It gives us a clean API and solves multiple problems. It is in major browsers and JS engines since Chrome 73+ / Node 12+ and Firefox 67+.
The method returns an iterator and is used as follows:
const string = "something format_abc";
const regexp = /(?:^|\s)format_(.*?)(?:\s|$)/g;
const matches = string.matchAll(regexp);
for (const match of matches) {
console.log(match);
console.log(match.index)
}
As it returns an iterator, we can say it's lazy, this is useful when handling particularly large numbers of capturing groups, or very large strings. But if you need, the result can be easily transformed into an Array by using the spread syntax or the Array.from method:
function getFirstGroup(regexp, str) {
const array = [...str.matchAll(regexp)];
return array.map(m => m[1]);
}
// or:
function getFirstGroup(regexp, str) {
return Array.from(str.matchAll(regexp), m => m[1]);
}
In the meantime, while this proposal gets more wide support, you can use the official shim package.
Also, the internal workings of the method are simple. An equivalent implementation using a generator function would be as follows:
function* matchAll(str, regexp) {
const flags = regexp.global ? regexp.flags : regexp.flags + "g";
const re = new RegExp(regexp, flags);
let match;
while (match = re.exec(str)) {
yield match;
}
}
A copy of the original regexp is created; this is to avoid side-effects due to the mutation of the lastIndex property when going through the multple matches.
Also, we need to ensure the regexp has the global flag to avoid an infinite loop.
I'm also happy to see that even this StackOverflow question was referenced in the discussions of the proposal.
original answer
You can access capturing groups like this:
var myString = "something format_abc";
var myRegexp = /(?:^|\s)format_(.*?)(?:\s|$)/g;
var myRegexp = new RegExp("(?:^|\s)format_(.*?)(?:\s|$)", "g");
var matches = myRegexp.exec(myString);
console.log(matches[1]); // abc
And if there are multiple matches you can iterate over them:
var myString = "something format_abc";
var myRegexp = new RegExp("(?:^|\s)format_(.*?)(?:\s|$)", "g");
match = myRegexp.exec(myString);
while (match != null) {
// matched text: match[0]
// match start: match.index
// capturing group n: match[n]
console.log(match[0])
match = myRegexp.exec(myString);
}
Here’s a method you can use to get the n​th capturing group for each match:
function getMatches(string, regex, index) {
index || (index = 1); // default to the first capturing group
var matches = [];
var match;
while (match = regex.exec(string)) {
matches.push(match[index]);
}
return matches;
}
// Example :
var myString = 'something format_abc something format_def something format_ghi';
var myRegEx = /(?:^|\s)format_(.*?)(?:\s|$)/g;
// Get an array containing the first capturing group for every match
var matches = getMatches(myString, myRegEx, 1);
// Log results
document.write(matches.length + ' matches found: ' + JSON.stringify(matches))
console.log(matches);
var myString = "something format_abc";
var arr = myString.match(/\bformat_(.*?)\b/);
console.log(arr[0] + " " + arr[1]);
The \b isn't exactly the same thing. (It works on --format_foo/, but doesn't work on format_a_b) But I wanted to show an alternative to your expression, which is fine. Of course, the match call is the important thing.
Last but not least, I found one line of code that worked fine for me (JS ES6):
let reg = /#([\S]+)/igm; // Get hashtags.
let string = 'mi alegría es total! ✌🙌\n#fiestasdefindeaño #PadreHijo #buenosmomentos #france #paris';
let matches = (string.match(reg) || []).map(e => e.replace(reg, '$1'));
console.log(matches);
This will return:
['fiestasdefindeaño', 'PadreHijo', 'buenosmomentos', 'france', 'paris']
In regards to the multi-match parentheses examples above, I was looking for an answer here after not getting what I wanted from:
var matches = mystring.match(/(?:neededToMatchButNotWantedInResult)(matchWanted)/igm);
After looking at the slightly convoluted function calls with while and .push() above, it dawned on me that the problem can be solved very elegantly with mystring.replace() instead (the replacing is NOT the point, and isn't even done, the CLEAN, built-in recursive function call option for the second parameter is!):
var yourstring = 'something format_abc something format_def something format_ghi';
var matches = [];
yourstring.replace(/format_([^\s]+)/igm, function(m, p1){ matches.push(p1); } );
After this, I don't think I'm ever going to use .match() for hardly anything ever again.
String#matchAll (see the Stage 3 Draft / December 7, 2018 proposal), simplifies acccess to all groups in the match object (mind that Group 0 is the whole match, while further groups correspond to the capturing groups in the pattern):
With matchAll available, you can avoid the while loop and exec with /g... Instead, by using matchAll, you get back an iterator which you can use with the more convenient for...of, array spread, or Array.from() constructs
This method yields a similar output to Regex.Matches in C#, re.finditer in Python, preg_match_all in PHP.
See a JS demo (tested in Google Chrome 73.0.3683.67 (official build), beta (64-bit)):
var myString = "key1:value1, key2-value2!!#key3=value3";
var matches = myString.matchAll(/(\w+)[:=-](\w+)/g);
console.log([...matches]); // All match with capturing group values
The console.log([...matches]) shows
You may also get match value or specific group values using
let matchData = "key1:value1, key2-value2!!#key3=value3".matchAll(/(\w+)[:=-](\w+)/g)
var matches = [...matchData]; // Note matchAll result is not re-iterable
console.log(Array.from(matches, m => m[0])); // All match (Group 0) values
// => [ "key1:value1", "key2-value2", "key3=value3" ]
console.log(Array.from(matches, m => m[1])); // All match (Group 1) values
// => [ "key1", "key2", "key3" ]
NOTE: See the browser compatibility details.
Terminology used in this answer:
Match indicates the result of running your RegEx pattern against your string like so: someString.match(regexPattern).
Matched patterns indicate all matched portions of the input string, which all reside inside the match array. These are all instances of your pattern inside the input string.
Matched groups indicate all groups to catch, defined in the RegEx pattern. (The patterns inside parentheses, like so: /format_(.*?)/g, where (.*?) would be a matched group.) These reside within matched patterns.
Description
To get access to the matched groups, in each of the matched patterns, you need a function or something similar to iterate over the match. There are a number of ways you can do this, as many of the other answers show. Most other answers use a while loop to iterate over all matched patterns, but I think we all know the potential dangers with that approach. It is necessary to match against a new RegExp() instead of just the pattern itself, which only got mentioned in a comment. This is because the .exec() method behaves similar to a generator function – it stops every time there is a match, but keeps its .lastIndex to continue from there on the next .exec() call.
Code examples
Below is an example of a function searchString which returns an Array of all matched patterns, where each match is an Array with all the containing matched groups. Instead of using a while loop, I have provided examples using both the Array.prototype.map() function as well as a more performant way – using a plain for-loop.
Concise versions (less code, more syntactic sugar)
These are less performant since they basically implement a forEach-loop instead of the faster for-loop.
// Concise ES6/ES2015 syntax
const searchString =
(string, pattern) =>
string
.match(new RegExp(pattern.source, pattern.flags))
.map(match =>
new RegExp(pattern.source, pattern.flags)
.exec(match));
// Or if you will, with ES5 syntax
function searchString(string, pattern) {
return string
.match(new RegExp(pattern.source, pattern.flags))
.map(match =>
new RegExp(pattern.source, pattern.flags)
.exec(match));
}
let string = "something format_abc",
pattern = /(?:^|\s)format_(.*?)(?:\s|$)/;
let result = searchString(string, pattern);
// [[" format_abc", "abc"], null]
// The trailing `null` disappears if you add the `global` flag
Performant versions (more code, less syntactic sugar)
// Performant ES6/ES2015 syntax
const searchString = (string, pattern) => {
let result = [];
const matches = string.match(new RegExp(pattern.source, pattern.flags));
for (let i = 0; i < matches.length; i++) {
result.push(new RegExp(pattern.source, pattern.flags).exec(matches[i]));
}
return result;
};
// Same thing, but with ES5 syntax
function searchString(string, pattern) {
var result = [];
var matches = string.match(new RegExp(pattern.source, pattern.flags));
for (var i = 0; i < matches.length; i++) {
result.push(new RegExp(pattern.source, pattern.flags).exec(matches[i]));
}
return result;
}
let string = "something format_abc",
pattern = /(?:^|\s)format_(.*?)(?:\s|$)/;
let result = searchString(string, pattern);
// [[" format_abc", "abc"], null]
// The trailing `null` disappears if you add the `global` flag
I have yet to compare these alternatives to the ones previously mentioned in the other answers, but I doubt this approach is less performant and less fail-safe than the others.
Your syntax probably isn't the best to keep. FF/Gecko defines RegExp as an extension of Function.
(FF2 went as far as typeof(/pattern/) == 'function')
It seems this is specific to FF -- IE, Opera, and Chrome all throw exceptions for it.
Instead, use either method previously mentioned by others: RegExp#exec or String#match.
They offer the same results:
var regex = /(?:^|\s)format_(.*?)(?:\s|$)/;
var input = "something format_abc";
regex(input); //=> [" format_abc", "abc"]
regex.exec(input); //=> [" format_abc", "abc"]
input.match(regex); //=> [" format_abc", "abc"]
There is no need to invoke the exec method! You can use "match" method directly on the string. Just don't forget the parentheses.
var str = "This is cool";
var matches = str.match(/(This is)( cool)$/);
console.log( JSON.stringify(matches) ); // will print ["This is cool","This is"," cool"] or something like that...
Position 0 has a string with all the results. Position 1 has the first match represented by parentheses, and position 2 has the second match isolated in your parentheses. Nested parentheses are tricky, so beware!
With es2018 you can now String.match() with named groups, makes your regex more explicit of what it was trying to do.
const url =
'https://stackoverflow.com/questions/432493/how-do-you-access-the-matched-groups-in-a-javascript-regular-expression?some=parameter';
const regex = /(?<protocol>https?):\/\/(?<hostname>[\w-\.]*)\/(?<pathname>[\w-\./]+)\??(?<querystring>.*?)?$/;
const { groups: segments } = url.match(regex);
console.log(segments);
and you'll get something like
{protocol: "https", hostname: "stackoverflow.com", pathname: "questions/432493/how-do-you-access-the-matched-groups-in-a-javascript-regular-expression", querystring: "some=parameter"}
A one liner that is practical only if you have a single pair of parenthesis:
while ( ( match = myRegex.exec( myStr ) ) && matches.push( match[1] ) ) {};
Using your code:
console.log(arr[1]); // prints: abc
console.log(arr[0]); // prints: format_abc
Edit: Safari 3, if it matters.
function getMatches(string, regex, index) {
index || (index = 1); // default to the first capturing group
var matches = [];
var match;
while (match = regex.exec(string)) {
matches.push(match[index]);
}
return matches;
}
// Example :
var myString = 'Rs.200 is Debited to A/c ...2031 on 02-12-14 20:05:49 (Clear Bal Rs.66248.77) AT ATM. TollFree 1800223344 18001024455 (6am-10pm)';
var myRegEx = /clear bal.+?(\d+\.?\d{2})/gi;
// Get an array containing the first capturing group for every match
var matches = getMatches(myString, myRegEx, 1);
// Log results
document.write(matches.length + ' matches found: ' + JSON.stringify(matches))
console.log(matches);
function getMatches(string, regex, index) {
index || (index = 1); // default to the first capturing group
var matches = [];
var match;
while (match = regex.exec(string)) {
matches.push(match[index]);
}
return matches;
}
// Example :
var myString = 'something format_abc something format_def something format_ghi';
var myRegEx = /(?:^|\s)format_(.*?)(?:\s|$)/g;
// Get an array containing the first capturing group for every match
var matches = getMatches(myString, myRegEx, 1);
// Log results
document.write(matches.length + ' matches found: ' + JSON.stringify(matches))
console.log(matches);
Your code works for me (FF3 on Mac) even if I agree with PhiLo that the regex should probably be:
/\bformat_(.*?)\b/
(But, of course, I'm not sure because I don't know the context of the regex.)
As #cms said in ECMAScript (ECMA-262) you can use matchAll. It return an iterator and by putting it in [... ] (spread operator) it converts to an array.(this regex extract urls of file names)
let text = `File1 File2`;
let fileUrls = [...text.matchAll(/href="(http\:\/\/[^"]+\.\w{3})\"/g)].map(r => r[1]);
console.log(fileUrls);
/*Regex function for extracting object from "window.location.search" string.
*/
var search = "?a=3&b=4&c=7"; // Example search string
var getSearchObj = function (searchString) {
var match, key, value, obj = {};
var pattern = /(\w+)=(\w+)/g;
var search = searchString.substr(1); // Remove '?'
while (match = pattern.exec(search)) {
obj[match[0].split('=')[0]] = match[0].split('=')[1];
}
return obj;
};
console.log(getSearchObj(search));
You don't really need an explicit loop to parse multiple matches — pass a replacement function as the second argument as described in: String.prototype.replace(regex, func):
var str = "Our chief weapon is {1}, {0} and {2}!";
var params= ['surprise', 'fear', 'ruthless efficiency'];
var patt = /{([^}]+)}/g;
str=str.replace(patt, function(m0, m1, position){return params[parseInt(m1)];});
document.write(str);
The m0 argument represents the full matched substring {0}, {1}, etc. m1 represents the first matching group, i.e. the part enclosed in brackets in the regex which is 0 for the first match. And position is the starting index within the string where the matching group was found — unused in this case.
We can access the matched group in a regular expressions by using backslash followed by number of the matching group:
/([a-z])\1/
In the code \1 represented matched by first group ([a-z])
I you are like me and wish regex would return an Object like this:
{
match: '...',
matchAtIndex: 0,
capturedGroups: [ '...', '...' ]
}
then snip the function from below
/**
* #param {string | number} input
* The input string to match
* #param {regex | string} expression
* Regular expression
* #param {string} flags
* Optional Flags
*
* #returns {array}
* [{
match: '...',
matchAtIndex: 0,
capturedGroups: [ '...', '...' ]
}]
*/
function regexMatch(input, expression, flags = "g") {
let regex = expression instanceof RegExp ? expression : new RegExp(expression, flags)
let matches = input.matchAll(regex)
matches = [...matches]
return matches.map(item => {
return {
match: item[0],
matchAtIndex: item.index,
capturedGroups: item.length > 1 ? item.slice(1) : undefined
}
})
}
let input = "key1:value1, key2:value2 "
let regex = /(\w+):(\w+)/g
let matches = regexMatch(input, regex)
console.log(matches)
One line solution:
const matches = (text,regex) => [...text.matchAll(regex)].map(([match])=>match)
So you can use this way (must use /g):
matches("something format_abc", /(?:^|\s)format_(.*?)(?:\s|$)/g)
result:
[" format_abc"]
JUST USE RegExp.$1...$n th group
eg:
1.To match 1st group RegExp.$1
To match 2nd group RegExp.$2
if you use 3 group in regex likey(note use after string.match(regex))
RegExp.$1 RegExp.$2 RegExp.$3
var str = "The rain in ${india} stays safe";
var res = str.match(/\${(.*?)\}/ig);
//i used only one group in above example so RegExp.$1
console.log(RegExp.$1)
//easiest way is use RegExp.$1 1st group in regex and 2nd grounp like
//RegExp.$2 if exist use after match
var regex=/\${(.*?)\}/ig;
var str = "The rain in ${SPAIN} stays ${mainly} in the plain";
var res = str.match(regex);
for (const match of res) {
var res = match.match(regex);
console.log(match);
console.log(RegExp.$1)
}
Get all group occurrence
let m=[], s = "something format_abc format_def format_ghi";
s.replace(/(?:^|\s)format_(.*?)(?:\s|$)/g, (x,y)=> m.push(y));
console.log(m);
I thought you just want to grab all the words containing the abc substring and store the matched group/entries, so I made this script:
s = 'something format_abc another word abc abc_somestring'
console.log(s.match(/\b\w*abc\w*\b/igm));
\b - a word boundary
\w* - 0+ word chars
abc - your exact match
\w* - 0+ word chars
\b - a word boundary
References: Regex: Match all the words that contains some word
https://javascript.info/regexp-introduction

JavaScript Split with RegEx without Global Match

I have an expression.
var expression = "Q101='You will have an answer here like a string for instance.'"
I have a regular expression that searches the expression.
var regEx = new regExp(/=|<>|like/)
I want to split the expression using the regular expression.
var result = expression.split(regExp)
This will return the following:
["Q101", "'You will have an answer here ", " a string for instance'"]
This is not what I want.
I should have:
["Q101", "'You will have an answer here like a string for instance'"]
How do I use the regular expression above to split only on the first match?
Since you only want to grab the two parts either side of the first delimiter it might be easier to use String.match and discard the whole match:
var expression = "Q101='You will have an answer here like a string for instance.'";
var parts = expression.match(/^(.*?)(?:=|<>|like)(.*)$/);
parts.shift();
console.log(parts);
expression = "Q101like'This answer uses like twice'";
parts = expression.match(/^(.*?)(?:=|<>|like)(.*)$/);
parts.shift();
console.log(parts);
JavaScript's split method won't quite do what you want, because it will either split on all matches, or stop after N matches. You need an extra step to find the first match, then split once by the first match using a custom function:
function splitMatch(string, match) {
var splitString = match[0];
var result = [
expression.slice(0, match.index),
expression.slice(match.index + splitString.length)
];
return result;
}
var expression = "Q101='You will have an answer here like a string for instance.'"
var regEx = new RegExp(/=|<>|like/)
var match = regEx.exec(expression)
if (match) {
var result = splitMatch(expression, match);
console.log(result);
}
While JavaScript's split method does have an optional limit parameter, it simply discards the parts of the result that make it too long (unlike, e.g. Python's split). To do this in JS, you'll need to split it manually, considering the length of the match —
const exp = "Q101='You will have an answer here like a string for instance.'"
const splitRxp = /=|<>|like/
const splitPos = exp.search(splitRxp)
const splitStr = exp.match(splitRxp)[0]
const result = splitPos != -1 ? (
[
exp.substring(0, splitPos),
exp.substring(splitPos + splitStr.length),
]
) : (
null
);
console.log(result)

How can I match an element after certain string, but not include it? [duplicate]

I want to match a portion of a string using a regular expression and then access that parenthesized substring:
var myString = "something format_abc"; // I want "abc"
var arr = /(?:^|\s)format_(.*?)(?:\s|$)/.exec(myString);
console.log(arr); // Prints: [" format_abc", "abc"] .. so far so good.
console.log(arr[1]); // Prints: undefined (???)
console.log(arr[0]); // Prints: format_undefined (!!!)
What am I doing wrong?
I've discovered that there was nothing wrong with the regular expression code above: the actual string which I was testing against was this:
"date format_%A"
Reporting that "%A" is undefined seems a very strange behaviour, but it is not directly related to this question, so I've opened a new one, Why is a matched substring returning "undefined" in JavaScript?.
The issue was that console.log takes its parameters like a printf statement, and since the string I was logging ("%A") had a special value, it was trying to find the value of the next parameter.
Update: 2019-09-10
The old way to iterate over multiple matches was not very intuitive. This lead to the proposal of the String.prototype.matchAll method. This new method is in the ECMAScript 2020 specification. It gives us a clean API and solves multiple problems. It is in major browsers and JS engines since Chrome 73+ / Node 12+ and Firefox 67+.
The method returns an iterator and is used as follows:
const string = "something format_abc";
const regexp = /(?:^|\s)format_(.*?)(?:\s|$)/g;
const matches = string.matchAll(regexp);
for (const match of matches) {
console.log(match);
console.log(match.index)
}
As it returns an iterator, we can say it's lazy, this is useful when handling particularly large numbers of capturing groups, or very large strings. But if you need, the result can be easily transformed into an Array by using the spread syntax or the Array.from method:
function getFirstGroup(regexp, str) {
const array = [...str.matchAll(regexp)];
return array.map(m => m[1]);
}
// or:
function getFirstGroup(regexp, str) {
return Array.from(str.matchAll(regexp), m => m[1]);
}
In the meantime, while this proposal gets more wide support, you can use the official shim package.
Also, the internal workings of the method are simple. An equivalent implementation using a generator function would be as follows:
function* matchAll(str, regexp) {
const flags = regexp.global ? regexp.flags : regexp.flags + "g";
const re = new RegExp(regexp, flags);
let match;
while (match = re.exec(str)) {
yield match;
}
}
A copy of the original regexp is created; this is to avoid side-effects due to the mutation of the lastIndex property when going through the multple matches.
Also, we need to ensure the regexp has the global flag to avoid an infinite loop.
I'm also happy to see that even this StackOverflow question was referenced in the discussions of the proposal.
original answer
You can access capturing groups like this:
var myString = "something format_abc";
var myRegexp = /(?:^|\s)format_(.*?)(?:\s|$)/g;
var myRegexp = new RegExp("(?:^|\s)format_(.*?)(?:\s|$)", "g");
var matches = myRegexp.exec(myString);
console.log(matches[1]); // abc
And if there are multiple matches you can iterate over them:
var myString = "something format_abc";
var myRegexp = new RegExp("(?:^|\s)format_(.*?)(?:\s|$)", "g");
match = myRegexp.exec(myString);
while (match != null) {
// matched text: match[0]
// match start: match.index
// capturing group n: match[n]
console.log(match[0])
match = myRegexp.exec(myString);
}
Here’s a method you can use to get the n​th capturing group for each match:
function getMatches(string, regex, index) {
index || (index = 1); // default to the first capturing group
var matches = [];
var match;
while (match = regex.exec(string)) {
matches.push(match[index]);
}
return matches;
}
// Example :
var myString = 'something format_abc something format_def something format_ghi';
var myRegEx = /(?:^|\s)format_(.*?)(?:\s|$)/g;
// Get an array containing the first capturing group for every match
var matches = getMatches(myString, myRegEx, 1);
// Log results
document.write(matches.length + ' matches found: ' + JSON.stringify(matches))
console.log(matches);
var myString = "something format_abc";
var arr = myString.match(/\bformat_(.*?)\b/);
console.log(arr[0] + " " + arr[1]);
The \b isn't exactly the same thing. (It works on --format_foo/, but doesn't work on format_a_b) But I wanted to show an alternative to your expression, which is fine. Of course, the match call is the important thing.
Last but not least, I found one line of code that worked fine for me (JS ES6):
let reg = /#([\S]+)/igm; // Get hashtags.
let string = 'mi alegría es total! ✌🙌\n#fiestasdefindeaño #PadreHijo #buenosmomentos #france #paris';
let matches = (string.match(reg) || []).map(e => e.replace(reg, '$1'));
console.log(matches);
This will return:
['fiestasdefindeaño', 'PadreHijo', 'buenosmomentos', 'france', 'paris']
In regards to the multi-match parentheses examples above, I was looking for an answer here after not getting what I wanted from:
var matches = mystring.match(/(?:neededToMatchButNotWantedInResult)(matchWanted)/igm);
After looking at the slightly convoluted function calls with while and .push() above, it dawned on me that the problem can be solved very elegantly with mystring.replace() instead (the replacing is NOT the point, and isn't even done, the CLEAN, built-in recursive function call option for the second parameter is!):
var yourstring = 'something format_abc something format_def something format_ghi';
var matches = [];
yourstring.replace(/format_([^\s]+)/igm, function(m, p1){ matches.push(p1); } );
After this, I don't think I'm ever going to use .match() for hardly anything ever again.
String#matchAll (see the Stage 3 Draft / December 7, 2018 proposal), simplifies acccess to all groups in the match object (mind that Group 0 is the whole match, while further groups correspond to the capturing groups in the pattern):
With matchAll available, you can avoid the while loop and exec with /g... Instead, by using matchAll, you get back an iterator which you can use with the more convenient for...of, array spread, or Array.from() constructs
This method yields a similar output to Regex.Matches in C#, re.finditer in Python, preg_match_all in PHP.
See a JS demo (tested in Google Chrome 73.0.3683.67 (official build), beta (64-bit)):
var myString = "key1:value1, key2-value2!!#key3=value3";
var matches = myString.matchAll(/(\w+)[:=-](\w+)/g);
console.log([...matches]); // All match with capturing group values
The console.log([...matches]) shows
You may also get match value or specific group values using
let matchData = "key1:value1, key2-value2!!#key3=value3".matchAll(/(\w+)[:=-](\w+)/g)
var matches = [...matchData]; // Note matchAll result is not re-iterable
console.log(Array.from(matches, m => m[0])); // All match (Group 0) values
// => [ "key1:value1", "key2-value2", "key3=value3" ]
console.log(Array.from(matches, m => m[1])); // All match (Group 1) values
// => [ "key1", "key2", "key3" ]
NOTE: See the browser compatibility details.
Terminology used in this answer:
Match indicates the result of running your RegEx pattern against your string like so: someString.match(regexPattern).
Matched patterns indicate all matched portions of the input string, which all reside inside the match array. These are all instances of your pattern inside the input string.
Matched groups indicate all groups to catch, defined in the RegEx pattern. (The patterns inside parentheses, like so: /format_(.*?)/g, where (.*?) would be a matched group.) These reside within matched patterns.
Description
To get access to the matched groups, in each of the matched patterns, you need a function or something similar to iterate over the match. There are a number of ways you can do this, as many of the other answers show. Most other answers use a while loop to iterate over all matched patterns, but I think we all know the potential dangers with that approach. It is necessary to match against a new RegExp() instead of just the pattern itself, which only got mentioned in a comment. This is because the .exec() method behaves similar to a generator function – it stops every time there is a match, but keeps its .lastIndex to continue from there on the next .exec() call.
Code examples
Below is an example of a function searchString which returns an Array of all matched patterns, where each match is an Array with all the containing matched groups. Instead of using a while loop, I have provided examples using both the Array.prototype.map() function as well as a more performant way – using a plain for-loop.
Concise versions (less code, more syntactic sugar)
These are less performant since they basically implement a forEach-loop instead of the faster for-loop.
// Concise ES6/ES2015 syntax
const searchString =
(string, pattern) =>
string
.match(new RegExp(pattern.source, pattern.flags))
.map(match =>
new RegExp(pattern.source, pattern.flags)
.exec(match));
// Or if you will, with ES5 syntax
function searchString(string, pattern) {
return string
.match(new RegExp(pattern.source, pattern.flags))
.map(match =>
new RegExp(pattern.source, pattern.flags)
.exec(match));
}
let string = "something format_abc",
pattern = /(?:^|\s)format_(.*?)(?:\s|$)/;
let result = searchString(string, pattern);
// [[" format_abc", "abc"], null]
// The trailing `null` disappears if you add the `global` flag
Performant versions (more code, less syntactic sugar)
// Performant ES6/ES2015 syntax
const searchString = (string, pattern) => {
let result = [];
const matches = string.match(new RegExp(pattern.source, pattern.flags));
for (let i = 0; i < matches.length; i++) {
result.push(new RegExp(pattern.source, pattern.flags).exec(matches[i]));
}
return result;
};
// Same thing, but with ES5 syntax
function searchString(string, pattern) {
var result = [];
var matches = string.match(new RegExp(pattern.source, pattern.flags));
for (var i = 0; i < matches.length; i++) {
result.push(new RegExp(pattern.source, pattern.flags).exec(matches[i]));
}
return result;
}
let string = "something format_abc",
pattern = /(?:^|\s)format_(.*?)(?:\s|$)/;
let result = searchString(string, pattern);
// [[" format_abc", "abc"], null]
// The trailing `null` disappears if you add the `global` flag
I have yet to compare these alternatives to the ones previously mentioned in the other answers, but I doubt this approach is less performant and less fail-safe than the others.
Your syntax probably isn't the best to keep. FF/Gecko defines RegExp as an extension of Function.
(FF2 went as far as typeof(/pattern/) == 'function')
It seems this is specific to FF -- IE, Opera, and Chrome all throw exceptions for it.
Instead, use either method previously mentioned by others: RegExp#exec or String#match.
They offer the same results:
var regex = /(?:^|\s)format_(.*?)(?:\s|$)/;
var input = "something format_abc";
regex(input); //=> [" format_abc", "abc"]
regex.exec(input); //=> [" format_abc", "abc"]
input.match(regex); //=> [" format_abc", "abc"]
There is no need to invoke the exec method! You can use "match" method directly on the string. Just don't forget the parentheses.
var str = "This is cool";
var matches = str.match(/(This is)( cool)$/);
console.log( JSON.stringify(matches) ); // will print ["This is cool","This is"," cool"] or something like that...
Position 0 has a string with all the results. Position 1 has the first match represented by parentheses, and position 2 has the second match isolated in your parentheses. Nested parentheses are tricky, so beware!
With es2018 you can now String.match() with named groups, makes your regex more explicit of what it was trying to do.
const url =
'https://stackoverflow.com/questions/432493/how-do-you-access-the-matched-groups-in-a-javascript-regular-expression?some=parameter';
const regex = /(?<protocol>https?):\/\/(?<hostname>[\w-\.]*)\/(?<pathname>[\w-\./]+)\??(?<querystring>.*?)?$/;
const { groups: segments } = url.match(regex);
console.log(segments);
and you'll get something like
{protocol: "https", hostname: "stackoverflow.com", pathname: "questions/432493/how-do-you-access-the-matched-groups-in-a-javascript-regular-expression", querystring: "some=parameter"}
A one liner that is practical only if you have a single pair of parenthesis:
while ( ( match = myRegex.exec( myStr ) ) && matches.push( match[1] ) ) {};
Using your code:
console.log(arr[1]); // prints: abc
console.log(arr[0]); // prints: format_abc
Edit: Safari 3, if it matters.
function getMatches(string, regex, index) {
index || (index = 1); // default to the first capturing group
var matches = [];
var match;
while (match = regex.exec(string)) {
matches.push(match[index]);
}
return matches;
}
// Example :
var myString = 'Rs.200 is Debited to A/c ...2031 on 02-12-14 20:05:49 (Clear Bal Rs.66248.77) AT ATM. TollFree 1800223344 18001024455 (6am-10pm)';
var myRegEx = /clear bal.+?(\d+\.?\d{2})/gi;
// Get an array containing the first capturing group for every match
var matches = getMatches(myString, myRegEx, 1);
// Log results
document.write(matches.length + ' matches found: ' + JSON.stringify(matches))
console.log(matches);
function getMatches(string, regex, index) {
index || (index = 1); // default to the first capturing group
var matches = [];
var match;
while (match = regex.exec(string)) {
matches.push(match[index]);
}
return matches;
}
// Example :
var myString = 'something format_abc something format_def something format_ghi';
var myRegEx = /(?:^|\s)format_(.*?)(?:\s|$)/g;
// Get an array containing the first capturing group for every match
var matches = getMatches(myString, myRegEx, 1);
// Log results
document.write(matches.length + ' matches found: ' + JSON.stringify(matches))
console.log(matches);
Your code works for me (FF3 on Mac) even if I agree with PhiLo that the regex should probably be:
/\bformat_(.*?)\b/
(But, of course, I'm not sure because I don't know the context of the regex.)
As #cms said in ECMAScript (ECMA-262) you can use matchAll. It return an iterator and by putting it in [... ] (spread operator) it converts to an array.(this regex extract urls of file names)
let text = `File1 File2`;
let fileUrls = [...text.matchAll(/href="(http\:\/\/[^"]+\.\w{3})\"/g)].map(r => r[1]);
console.log(fileUrls);
/*Regex function for extracting object from "window.location.search" string.
*/
var search = "?a=3&b=4&c=7"; // Example search string
var getSearchObj = function (searchString) {
var match, key, value, obj = {};
var pattern = /(\w+)=(\w+)/g;
var search = searchString.substr(1); // Remove '?'
while (match = pattern.exec(search)) {
obj[match[0].split('=')[0]] = match[0].split('=')[1];
}
return obj;
};
console.log(getSearchObj(search));
You don't really need an explicit loop to parse multiple matches — pass a replacement function as the second argument as described in: String.prototype.replace(regex, func):
var str = "Our chief weapon is {1}, {0} and {2}!";
var params= ['surprise', 'fear', 'ruthless efficiency'];
var patt = /{([^}]+)}/g;
str=str.replace(patt, function(m0, m1, position){return params[parseInt(m1)];});
document.write(str);
The m0 argument represents the full matched substring {0}, {1}, etc. m1 represents the first matching group, i.e. the part enclosed in brackets in the regex which is 0 for the first match. And position is the starting index within the string where the matching group was found — unused in this case.
We can access the matched group in a regular expressions by using backslash followed by number of the matching group:
/([a-z])\1/
In the code \1 represented matched by first group ([a-z])
I you are like me and wish regex would return an Object like this:
{
match: '...',
matchAtIndex: 0,
capturedGroups: [ '...', '...' ]
}
then snip the function from below
/**
* #param {string | number} input
* The input string to match
* #param {regex | string} expression
* Regular expression
* #param {string} flags
* Optional Flags
*
* #returns {array}
* [{
match: '...',
matchAtIndex: 0,
capturedGroups: [ '...', '...' ]
}]
*/
function regexMatch(input, expression, flags = "g") {
let regex = expression instanceof RegExp ? expression : new RegExp(expression, flags)
let matches = input.matchAll(regex)
matches = [...matches]
return matches.map(item => {
return {
match: item[0],
matchAtIndex: item.index,
capturedGroups: item.length > 1 ? item.slice(1) : undefined
}
})
}
let input = "key1:value1, key2:value2 "
let regex = /(\w+):(\w+)/g
let matches = regexMatch(input, regex)
console.log(matches)
One line solution:
const matches = (text,regex) => [...text.matchAll(regex)].map(([match])=>match)
So you can use this way (must use /g):
matches("something format_abc", /(?:^|\s)format_(.*?)(?:\s|$)/g)
result:
[" format_abc"]
JUST USE RegExp.$1...$n th group
eg:
1.To match 1st group RegExp.$1
To match 2nd group RegExp.$2
if you use 3 group in regex likey(note use after string.match(regex))
RegExp.$1 RegExp.$2 RegExp.$3
var str = "The rain in ${india} stays safe";
var res = str.match(/\${(.*?)\}/ig);
//i used only one group in above example so RegExp.$1
console.log(RegExp.$1)
//easiest way is use RegExp.$1 1st group in regex and 2nd grounp like
//RegExp.$2 if exist use after match
var regex=/\${(.*?)\}/ig;
var str = "The rain in ${SPAIN} stays ${mainly} in the plain";
var res = str.match(regex);
for (const match of res) {
var res = match.match(regex);
console.log(match);
console.log(RegExp.$1)
}
Get all group occurrence
let m=[], s = "something format_abc format_def format_ghi";
s.replace(/(?:^|\s)format_(.*?)(?:\s|$)/g, (x,y)=> m.push(y));
console.log(m);
I thought you just want to grab all the words containing the abc substring and store the matched group/entries, so I made this script:
s = 'something format_abc another word abc abc_somestring'
console.log(s.match(/\b\w*abc\w*\b/igm));
\b - a word boundary
\w* - 0+ word chars
abc - your exact match
\w* - 0+ word chars
\b - a word boundary
References: Regex: Match all the words that contains some word
https://javascript.info/regexp-introduction

Javascript regex: How do you get the substring match while using match() [duplicate]

I want to match a portion of a string using a regular expression and then access that parenthesized substring:
var myString = "something format_abc"; // I want "abc"
var arr = /(?:^|\s)format_(.*?)(?:\s|$)/.exec(myString);
console.log(arr); // Prints: [" format_abc", "abc"] .. so far so good.
console.log(arr[1]); // Prints: undefined (???)
console.log(arr[0]); // Prints: format_undefined (!!!)
What am I doing wrong?
I've discovered that there was nothing wrong with the regular expression code above: the actual string which I was testing against was this:
"date format_%A"
Reporting that "%A" is undefined seems a very strange behaviour, but it is not directly related to this question, so I've opened a new one, Why is a matched substring returning "undefined" in JavaScript?.
The issue was that console.log takes its parameters like a printf statement, and since the string I was logging ("%A") had a special value, it was trying to find the value of the next parameter.
Update: 2019-09-10
The old way to iterate over multiple matches was not very intuitive. This lead to the proposal of the String.prototype.matchAll method. This new method is in the ECMAScript 2020 specification. It gives us a clean API and solves multiple problems. It is in major browsers and JS engines since Chrome 73+ / Node 12+ and Firefox 67+.
The method returns an iterator and is used as follows:
const string = "something format_abc";
const regexp = /(?:^|\s)format_(.*?)(?:\s|$)/g;
const matches = string.matchAll(regexp);
for (const match of matches) {
console.log(match);
console.log(match.index)
}
As it returns an iterator, we can say it's lazy, this is useful when handling particularly large numbers of capturing groups, or very large strings. But if you need, the result can be easily transformed into an Array by using the spread syntax or the Array.from method:
function getFirstGroup(regexp, str) {
const array = [...str.matchAll(regexp)];
return array.map(m => m[1]);
}
// or:
function getFirstGroup(regexp, str) {
return Array.from(str.matchAll(regexp), m => m[1]);
}
In the meantime, while this proposal gets more wide support, you can use the official shim package.
Also, the internal workings of the method are simple. An equivalent implementation using a generator function would be as follows:
function* matchAll(str, regexp) {
const flags = regexp.global ? regexp.flags : regexp.flags + "g";
const re = new RegExp(regexp, flags);
let match;
while (match = re.exec(str)) {
yield match;
}
}
A copy of the original regexp is created; this is to avoid side-effects due to the mutation of the lastIndex property when going through the multple matches.
Also, we need to ensure the regexp has the global flag to avoid an infinite loop.
I'm also happy to see that even this StackOverflow question was referenced in the discussions of the proposal.
original answer
You can access capturing groups like this:
var myString = "something format_abc";
var myRegexp = /(?:^|\s)format_(.*?)(?:\s|$)/g;
var myRegexp = new RegExp("(?:^|\s)format_(.*?)(?:\s|$)", "g");
var matches = myRegexp.exec(myString);
console.log(matches[1]); // abc
And if there are multiple matches you can iterate over them:
var myString = "something format_abc";
var myRegexp = new RegExp("(?:^|\s)format_(.*?)(?:\s|$)", "g");
match = myRegexp.exec(myString);
while (match != null) {
// matched text: match[0]
// match start: match.index
// capturing group n: match[n]
console.log(match[0])
match = myRegexp.exec(myString);
}
Here’s a method you can use to get the n​th capturing group for each match:
function getMatches(string, regex, index) {
index || (index = 1); // default to the first capturing group
var matches = [];
var match;
while (match = regex.exec(string)) {
matches.push(match[index]);
}
return matches;
}
// Example :
var myString = 'something format_abc something format_def something format_ghi';
var myRegEx = /(?:^|\s)format_(.*?)(?:\s|$)/g;
// Get an array containing the first capturing group for every match
var matches = getMatches(myString, myRegEx, 1);
// Log results
document.write(matches.length + ' matches found: ' + JSON.stringify(matches))
console.log(matches);
var myString = "something format_abc";
var arr = myString.match(/\bformat_(.*?)\b/);
console.log(arr[0] + " " + arr[1]);
The \b isn't exactly the same thing. (It works on --format_foo/, but doesn't work on format_a_b) But I wanted to show an alternative to your expression, which is fine. Of course, the match call is the important thing.
Last but not least, I found one line of code that worked fine for me (JS ES6):
let reg = /#([\S]+)/igm; // Get hashtags.
let string = 'mi alegría es total! ✌🙌\n#fiestasdefindeaño #PadreHijo #buenosmomentos #france #paris';
let matches = (string.match(reg) || []).map(e => e.replace(reg, '$1'));
console.log(matches);
This will return:
['fiestasdefindeaño', 'PadreHijo', 'buenosmomentos', 'france', 'paris']
In regards to the multi-match parentheses examples above, I was looking for an answer here after not getting what I wanted from:
var matches = mystring.match(/(?:neededToMatchButNotWantedInResult)(matchWanted)/igm);
After looking at the slightly convoluted function calls with while and .push() above, it dawned on me that the problem can be solved very elegantly with mystring.replace() instead (the replacing is NOT the point, and isn't even done, the CLEAN, built-in recursive function call option for the second parameter is!):
var yourstring = 'something format_abc something format_def something format_ghi';
var matches = [];
yourstring.replace(/format_([^\s]+)/igm, function(m, p1){ matches.push(p1); } );
After this, I don't think I'm ever going to use .match() for hardly anything ever again.
String#matchAll (see the Stage 3 Draft / December 7, 2018 proposal), simplifies acccess to all groups in the match object (mind that Group 0 is the whole match, while further groups correspond to the capturing groups in the pattern):
With matchAll available, you can avoid the while loop and exec with /g... Instead, by using matchAll, you get back an iterator which you can use with the more convenient for...of, array spread, or Array.from() constructs
This method yields a similar output to Regex.Matches in C#, re.finditer in Python, preg_match_all in PHP.
See a JS demo (tested in Google Chrome 73.0.3683.67 (official build), beta (64-bit)):
var myString = "key1:value1, key2-value2!!#key3=value3";
var matches = myString.matchAll(/(\w+)[:=-](\w+)/g);
console.log([...matches]); // All match with capturing group values
The console.log([...matches]) shows
You may also get match value or specific group values using
let matchData = "key1:value1, key2-value2!!#key3=value3".matchAll(/(\w+)[:=-](\w+)/g)
var matches = [...matchData]; // Note matchAll result is not re-iterable
console.log(Array.from(matches, m => m[0])); // All match (Group 0) values
// => [ "key1:value1", "key2-value2", "key3=value3" ]
console.log(Array.from(matches, m => m[1])); // All match (Group 1) values
// => [ "key1", "key2", "key3" ]
NOTE: See the browser compatibility details.
Terminology used in this answer:
Match indicates the result of running your RegEx pattern against your string like so: someString.match(regexPattern).
Matched patterns indicate all matched portions of the input string, which all reside inside the match array. These are all instances of your pattern inside the input string.
Matched groups indicate all groups to catch, defined in the RegEx pattern. (The patterns inside parentheses, like so: /format_(.*?)/g, where (.*?) would be a matched group.) These reside within matched patterns.
Description
To get access to the matched groups, in each of the matched patterns, you need a function or something similar to iterate over the match. There are a number of ways you can do this, as many of the other answers show. Most other answers use a while loop to iterate over all matched patterns, but I think we all know the potential dangers with that approach. It is necessary to match against a new RegExp() instead of just the pattern itself, which only got mentioned in a comment. This is because the .exec() method behaves similar to a generator function – it stops every time there is a match, but keeps its .lastIndex to continue from there on the next .exec() call.
Code examples
Below is an example of a function searchString which returns an Array of all matched patterns, where each match is an Array with all the containing matched groups. Instead of using a while loop, I have provided examples using both the Array.prototype.map() function as well as a more performant way – using a plain for-loop.
Concise versions (less code, more syntactic sugar)
These are less performant since they basically implement a forEach-loop instead of the faster for-loop.
// Concise ES6/ES2015 syntax
const searchString =
(string, pattern) =>
string
.match(new RegExp(pattern.source, pattern.flags))
.map(match =>
new RegExp(pattern.source, pattern.flags)
.exec(match));
// Or if you will, with ES5 syntax
function searchString(string, pattern) {
return string
.match(new RegExp(pattern.source, pattern.flags))
.map(match =>
new RegExp(pattern.source, pattern.flags)
.exec(match));
}
let string = "something format_abc",
pattern = /(?:^|\s)format_(.*?)(?:\s|$)/;
let result = searchString(string, pattern);
// [[" format_abc", "abc"], null]
// The trailing `null` disappears if you add the `global` flag
Performant versions (more code, less syntactic sugar)
// Performant ES6/ES2015 syntax
const searchString = (string, pattern) => {
let result = [];
const matches = string.match(new RegExp(pattern.source, pattern.flags));
for (let i = 0; i < matches.length; i++) {
result.push(new RegExp(pattern.source, pattern.flags).exec(matches[i]));
}
return result;
};
// Same thing, but with ES5 syntax
function searchString(string, pattern) {
var result = [];
var matches = string.match(new RegExp(pattern.source, pattern.flags));
for (var i = 0; i < matches.length; i++) {
result.push(new RegExp(pattern.source, pattern.flags).exec(matches[i]));
}
return result;
}
let string = "something format_abc",
pattern = /(?:^|\s)format_(.*?)(?:\s|$)/;
let result = searchString(string, pattern);
// [[" format_abc", "abc"], null]
// The trailing `null` disappears if you add the `global` flag
I have yet to compare these alternatives to the ones previously mentioned in the other answers, but I doubt this approach is less performant and less fail-safe than the others.
Your syntax probably isn't the best to keep. FF/Gecko defines RegExp as an extension of Function.
(FF2 went as far as typeof(/pattern/) == 'function')
It seems this is specific to FF -- IE, Opera, and Chrome all throw exceptions for it.
Instead, use either method previously mentioned by others: RegExp#exec or String#match.
They offer the same results:
var regex = /(?:^|\s)format_(.*?)(?:\s|$)/;
var input = "something format_abc";
regex(input); //=> [" format_abc", "abc"]
regex.exec(input); //=> [" format_abc", "abc"]
input.match(regex); //=> [" format_abc", "abc"]
There is no need to invoke the exec method! You can use "match" method directly on the string. Just don't forget the parentheses.
var str = "This is cool";
var matches = str.match(/(This is)( cool)$/);
console.log( JSON.stringify(matches) ); // will print ["This is cool","This is"," cool"] or something like that...
Position 0 has a string with all the results. Position 1 has the first match represented by parentheses, and position 2 has the second match isolated in your parentheses. Nested parentheses are tricky, so beware!
With es2018 you can now String.match() with named groups, makes your regex more explicit of what it was trying to do.
const url =
'https://stackoverflow.com/questions/432493/how-do-you-access-the-matched-groups-in-a-javascript-regular-expression?some=parameter';
const regex = /(?<protocol>https?):\/\/(?<hostname>[\w-\.]*)\/(?<pathname>[\w-\./]+)\??(?<querystring>.*?)?$/;
const { groups: segments } = url.match(regex);
console.log(segments);
and you'll get something like
{protocol: "https", hostname: "stackoverflow.com", pathname: "questions/432493/how-do-you-access-the-matched-groups-in-a-javascript-regular-expression", querystring: "some=parameter"}
A one liner that is practical only if you have a single pair of parenthesis:
while ( ( match = myRegex.exec( myStr ) ) && matches.push( match[1] ) ) {};
Using your code:
console.log(arr[1]); // prints: abc
console.log(arr[0]); // prints: format_abc
Edit: Safari 3, if it matters.
function getMatches(string, regex, index) {
index || (index = 1); // default to the first capturing group
var matches = [];
var match;
while (match = regex.exec(string)) {
matches.push(match[index]);
}
return matches;
}
// Example :
var myString = 'Rs.200 is Debited to A/c ...2031 on 02-12-14 20:05:49 (Clear Bal Rs.66248.77) AT ATM. TollFree 1800223344 18001024455 (6am-10pm)';
var myRegEx = /clear bal.+?(\d+\.?\d{2})/gi;
// Get an array containing the first capturing group for every match
var matches = getMatches(myString, myRegEx, 1);
// Log results
document.write(matches.length + ' matches found: ' + JSON.stringify(matches))
console.log(matches);
function getMatches(string, regex, index) {
index || (index = 1); // default to the first capturing group
var matches = [];
var match;
while (match = regex.exec(string)) {
matches.push(match[index]);
}
return matches;
}
// Example :
var myString = 'something format_abc something format_def something format_ghi';
var myRegEx = /(?:^|\s)format_(.*?)(?:\s|$)/g;
// Get an array containing the first capturing group for every match
var matches = getMatches(myString, myRegEx, 1);
// Log results
document.write(matches.length + ' matches found: ' + JSON.stringify(matches))
console.log(matches);
Your code works for me (FF3 on Mac) even if I agree with PhiLo that the regex should probably be:
/\bformat_(.*?)\b/
(But, of course, I'm not sure because I don't know the context of the regex.)
As #cms said in ECMAScript (ECMA-262) you can use matchAll. It return an iterator and by putting it in [... ] (spread operator) it converts to an array.(this regex extract urls of file names)
let text = `File1 File2`;
let fileUrls = [...text.matchAll(/href="(http\:\/\/[^"]+\.\w{3})\"/g)].map(r => r[1]);
console.log(fileUrls);
/*Regex function for extracting object from "window.location.search" string.
*/
var search = "?a=3&b=4&c=7"; // Example search string
var getSearchObj = function (searchString) {
var match, key, value, obj = {};
var pattern = /(\w+)=(\w+)/g;
var search = searchString.substr(1); // Remove '?'
while (match = pattern.exec(search)) {
obj[match[0].split('=')[0]] = match[0].split('=')[1];
}
return obj;
};
console.log(getSearchObj(search));
You don't really need an explicit loop to parse multiple matches — pass a replacement function as the second argument as described in: String.prototype.replace(regex, func):
var str = "Our chief weapon is {1}, {0} and {2}!";
var params= ['surprise', 'fear', 'ruthless efficiency'];
var patt = /{([^}]+)}/g;
str=str.replace(patt, function(m0, m1, position){return params[parseInt(m1)];});
document.write(str);
The m0 argument represents the full matched substring {0}, {1}, etc. m1 represents the first matching group, i.e. the part enclosed in brackets in the regex which is 0 for the first match. And position is the starting index within the string where the matching group was found — unused in this case.
We can access the matched group in a regular expressions by using backslash followed by number of the matching group:
/([a-z])\1/
In the code \1 represented matched by first group ([a-z])
I you are like me and wish regex would return an Object like this:
{
match: '...',
matchAtIndex: 0,
capturedGroups: [ '...', '...' ]
}
then snip the function from below
/**
* #param {string | number} input
* The input string to match
* #param {regex | string} expression
* Regular expression
* #param {string} flags
* Optional Flags
*
* #returns {array}
* [{
match: '...',
matchAtIndex: 0,
capturedGroups: [ '...', '...' ]
}]
*/
function regexMatch(input, expression, flags = "g") {
let regex = expression instanceof RegExp ? expression : new RegExp(expression, flags)
let matches = input.matchAll(regex)
matches = [...matches]
return matches.map(item => {
return {
match: item[0],
matchAtIndex: item.index,
capturedGroups: item.length > 1 ? item.slice(1) : undefined
}
})
}
let input = "key1:value1, key2:value2 "
let regex = /(\w+):(\w+)/g
let matches = regexMatch(input, regex)
console.log(matches)
One line solution:
const matches = (text,regex) => [...text.matchAll(regex)].map(([match])=>match)
So you can use this way (must use /g):
matches("something format_abc", /(?:^|\s)format_(.*?)(?:\s|$)/g)
result:
[" format_abc"]
JUST USE RegExp.$1...$n th group
eg:
1.To match 1st group RegExp.$1
To match 2nd group RegExp.$2
if you use 3 group in regex likey(note use after string.match(regex))
RegExp.$1 RegExp.$2 RegExp.$3
var str = "The rain in ${india} stays safe";
var res = str.match(/\${(.*?)\}/ig);
//i used only one group in above example so RegExp.$1
console.log(RegExp.$1)
//easiest way is use RegExp.$1 1st group in regex and 2nd grounp like
//RegExp.$2 if exist use after match
var regex=/\${(.*?)\}/ig;
var str = "The rain in ${SPAIN} stays ${mainly} in the plain";
var res = str.match(regex);
for (const match of res) {
var res = match.match(regex);
console.log(match);
console.log(RegExp.$1)
}
Get all group occurrence
let m=[], s = "something format_abc format_def format_ghi";
s.replace(/(?:^|\s)format_(.*?)(?:\s|$)/g, (x,y)=> m.push(y));
console.log(m);
I thought you just want to grab all the words containing the abc substring and store the matched group/entries, so I made this script:
s = 'something format_abc another word abc abc_somestring'
console.log(s.match(/\b\w*abc\w*\b/igm));
\b - a word boundary
\w* - 0+ word chars
abc - your exact match
\w* - 0+ word chars
\b - a word boundary
References: Regex: Match all the words that contains some word
https://javascript.info/regexp-introduction

Javascript regex pattern array with loop

I have attempted to create a function that will replace multiple regular expression values from an array. This works if the array does not contain quotation marks of any kind, this is problematic when I want to use a comma in my pattern. So I've been trying to find an alternative way of serving the pattern with no luck. Any ideas?
function removeCharacters(str){
//ucpa = unwanted character pattern array
//var ucpa = [/{/g,/}/g,/--/g,/---/g,/-/g,/^.\s/];
var ucpa = ["/{/","/}/","/--/","/---/","/-/","/^.\s/","/^,\s/"];
for (var i = 0; i < ucpa.length; i++){
//does not work
var pattern = new RegExp(ucpa[i],"g");
var str = str.replace(pattern, " ");
}
return str;
}
WORKING:
function removeCharacters(str){
//ucpa = unwanted character pattern array
var ucpa = [/{/g,/}/g,/--/g,/---/g,/-/g,/^.\s/,/^,\s/];
for (var i = 0; i < ucpa.length; i++){
var str = str.replace(ucpa[i], " ");
}
return str;
}
REFINED:
function removeCharacters(str){
var pattern = /[{}]|-{1,3}|^[.,]\s/g;
str = str.replace(pattern, " ");
return str;
}
The RegExp constructor takes raw expressions, not wrapped in / characters.
Therefore, all of your regexes contain two /s each, which isn't what you want.
Instead, you should make an array of actual regex literals:
var ucpa = [ /.../g, /",\/.../g, ... ];
You can also wrap all that into a single regex:
var str = str.replace(/[{}]|-{1,3}|^[.,]\s/g, " ")
although I'm not sure if that's exactly what you want since some of your regexes are nonsensical, for example ,^\s could never match.

Categories

Resources