Get the index of the group that matched in a regexp? - javascript

I have a regexp:
/(alpha)|(beta)|(gamma)/gi
Some text to match against:
Betamax. Digamma. Alphabet. Hebetation.
The matches are:
beta, gamma, alpha, beta
The values I am looking would be:
1,2,0,1
...can I ascertain the index of the group that matched in the regexp?

To access the groups, you will need to use .exec() repeatedly:
var regex = /(alpha)|(beta)|(gamma)/gi,
str = "Betamax. Digamma. Alphabet. Hebetation.";
for (var nums = [], match; match = regex.exec(str); )
nums.push(match.lastIndexOf(match[0]));
If you want the indizes zero-based, you could use
nums.push(match.slice(1).indexOf(match[0]));

Build your regex from an array of strings, and then lookup the matches with indexOf.

If we consider the exact sample you provided, the below will work:
var r = /(alpha)|(beta)|(gamma)/gi;
var s = "Betamax. Digammas. Alphabet. Habetation.";
var matched_indexes = [];
var cur_match = null;
while (cur_match = r.exec(s))
{
matched_indexes.push(cur_match[1] ? 0 : cur_match[2] ? 1 : 2 );
}
console.log(matched_indexes);
I leave it to you to make the content of the loop more dynamic / generic :p

Related

Replace string between second set of [ and ]

I am learning regex, and I got a doubt. Let's consider
var s = "YYYN[1-20]N[]NYY";
Now, I want to replace/insert the '1-8' between [ and ] at its second occurrence.
Then output should be
YYYN[1-20]N[1-8]NYY
For that I had tried using replace and passing a function through it as shown below:
var nth = 0;
s = s.replace(/\[([^)]+)\]/g, function(match, i, original) {
nth++;
return (nth === 1) ? "1-8" : match;
});
alert(s); // But It wont work
I think that regex is not matchIing the string that I am using.
How can I fix it?
You regex \[([^)]+)\] will not match empty square brackets since + requires at least 1 character other than ). I guess you wanted to write \[[^\]]*\].
Here is a fix for your solution:
var s = "YYYN[1-20]N[]NYY";
var nth = 0;
s = s.replace(/\[[^\]]*\]/g, function (match, i, original) {
nth++;
return (nth !== 1) ? "[1-8]" : match;
});
alert(s);
Here is another way of doing it:
var s = "YYYN[1-20]N[]NYY";
var nth = 0;
s = s.replace(/(.*)\[\]/, "$1[1-8]");
alert(s);
The regex (.*)\[\] matches and captures into Group 1 greedily as much text as possible (thus we get the last set of empty []), and then matches empty square brackets. Then we restore the text before [] with $1 backreference and add out string 1-8.
If it’s only two occurences of square brackets, then this will work:
/(.*\[.*?\].*\[).*?(\].*)/
This RegEx has “YYYN[1-20]N[” as the first capturing group and “]NYY” as the second.
I suggest using simple split and join operations:
var s = "YYYN[1-20]N[]NYY";
var arr = s.split(/\[/)
arr[2] = '1-8' + arr[2]
var r = arr.join('[')
//=> YYYN[1-20]N[1-8]NYY
You can use following regex :
var s = "YYYN[1-20]N[]NYY";
var nth = 0;
s = s.replace(/([^[]+\[(?:[^[]+)\][^[]+)\[[^[]+\](.+)/, "$1[1-8]$2");
alert(s);
The first part ([^[]+\[([^[]+)\][^[]+) will match a string contain first sub-string between []. and \[[^[]+\] would be the second one which you want and the last part (.+?) match the rest of your string.

Find the index of the last word character ( e.g.: /\w/ ) in a string with JS

I'm looking for a simple, fast way to find the index of the last, non-underscore, word character (i.e. digit or letter) in a string.
Example:
lastCharacterIndex("hello world!");
=> 10
Using RegExp.lastIndex:
s = "hello world!";
re = /[a-z0-9](?=\W*$)/gi; // global flag is important
re.exec(s);
index = re.lastIndex-1; // 10
function lastCharacterIndex(str){
var m = str.match(/\w[^\w]*$/);
return null===m ? -1 : str.lastIndexOf(m[0]);
}
You can search for a letter or digit followed only by non-letter non-digits, and take the index of the match (if there is a match).
var s = "hello world!";
var re = /[a-z\d][\W_]*$/i;
var match = re.exec(s);
var index = match ? match.index : -1;
alert(index); // 10
The match of a RegExp in JS is an Array, but it has two extra non-integer properties: "index" and "input".
Not sure of the index of it, but the last alphanum should be the last
character of match 0 using this
[\S\s]*[^\W_]

javascript:get strings between specific strings

I hava a long string like this detail?ww=hello"....detail?ww=that".I want't to get all strings between detail?ww= and the next ",I use .match(/detail\?ww=.+\"/g) but the array i get contains detail?ww= and ",how can I only get strings without detail?ww= and "
If JavaScript understood lookbehind, you could use that to match strings preceded by detail?ww= and followed by ;. Unfotunately that is not the case, so a little more processing is required:
var str = 'detail?ww=hello"....detail?ww=that"';
var regexG = /detail\?ww\=(.+?)\"/g;
var regex = /detail\?ww\=(.+?)\"/;
var matches = str.match(regexG).map(function(item){ return item.match(regex)[1] });
console.log(matches);
Some changes to your regexp:
+? - non-greedy quantifier.
You could do this using a basic loop :
var result = [],
s = 'detail?ww=hello"....detail?ww=that"',
r = /detail\?ww=([^"]+)/g,
m;
while (m = r.exec(s)) {
result.push(m[1]);
}
result; // ["hello", "that"]
[^"]+ : any char except double quotes, one or more times
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec
Keep in mind that map is not supported by IE8 and below : http://kangax.github.io/es5-compat-table/#Array.prototype.map. If you really don't like loops but need a cross browser compatible solution, here is an alternative :
var s = 'detail?ww=hello"....detail?ww=that"';
s = s.replace(/.*?detail\?ww=([^"]+")/g, '$1').match(/[^"]+/g) || [];
s; // ["hello", "that"]

How to match multiple sequences

How is it possible to match more than one string with regular expressions?
Here I want to match both name and txt, but only name is matched?
var reg = new RegExp('%([a-z]+)%', "g");
reg.exec('%name% some text %txt%');
You need to use String.match instead of exec:
'%name% some text %txt%'.match(reg);
Use match instead:
'%name% %txt%'.match(reg); //["%name%", "%txt%"]
exec only retrieves the first match (albeit with capturing groups).
If the capturing groups are important to you, you can use a loop:
var matches = [];
var str = '%name% some text %txt%';
var reg = new RegExp('%([a-z]+)%', "g");
while (match = reg.exec(str)){
matches.push(match);
}
If you only want to keep the captured groups, use this instead:
matches.push(match[1]);
The g flag does work but needs to be executed on the same string multiple times
var reg = new RegExp('%([a-z]+)%', "g");
var str = '%name% some text %txt%';
var result;
while( result = reg.exec( str ) ) { // returns array of current match
console.log( result[1] ); // index 0 is matched expression. Thereafter matched groups.
}​
The above outputs name & txt to the console.
Example here

Regex to grab strings between square brackets

I have the following string: pass[1][2011-08-21][total_passes]
How would I extract the items between the square brackets into an array? I tried
match(/\[(.*?)\]/);
var s = 'pass[1][2011-08-21][total_passes]';
var result = s.match(/\[(.*?)\]/);
console.log(result);
but this only returns [1].
Not sure how to do this.. Thanks in advance.
You are almost there, you just need a global match (note the /g flag):
match(/\[(.*?)\]/g);
Example: http://jsfiddle.net/kobi/Rbdj4/
If you want something that only captures the group (from MDN):
var s = "pass[1][2011-08-21][total_passes]";
var matches = [];
var pattern = /\[(.*?)\]/g;
var match;
while ((match = pattern.exec(s)) != null)
{
matches.push(match[1]);
}
Example: http://jsfiddle.net/kobi/6a7XN/
Another option (which I usually prefer), is abusing the replace callback:
var matches = [];
s.replace(/\[(.*?)\]/g, function(g0,g1){matches.push(g1);})
Example: http://jsfiddle.net/kobi/6CEzP/
var s = 'pass[1][2011-08-21][total_passes]';
r = s.match(/\[([^\]]*)\]/g);
r ; //# => [ '[1]', '[2011-08-21]', '[total_passes]' ]
example proving the edge case of unbalanced [];
var s = 'pass[1]]][2011-08-21][total_passes]';
r = s.match(/\[([^\]]*)\]/g);
r; //# => [ '[1]', '[2011-08-21]', '[total_passes]' ]
add the global flag to your regex , and iterate the array returned .
match(/\[(.*?)\]/g)
I'm not sure if you can get this directly into an array. But the following code should work to find all occurences and then process them:
var string = "pass[1][2011-08-21][total_passes]";
var regex = /\[([^\]]*)\]/g;
while (match = regex.exec(string)) {
alert(match[1]);
}
Please note: i really think you need the character class [^\]] here. Otherwise in my test the expression would match the hole string because ] is also matches by .*.
'pass[1][2011-08-21][total_passes]'.match(/\[.+?\]/g); // ["[1]","[2011-08-21]","[total_passes]"]
Explanation
\[ # match the opening [
Note: \ before [ tells that do NOT consider as a grouping symbol.
.+? # Accept one or more character but NOT greedy
\] # match the closing ] and again do NOT consider as a grouping symbol
/g # do NOT stop after the first match. Do it for the whole input string.
You can play with other combinations of the regular expression
https://regex101.com/r/IYDkNi/1
[C#]
string str1 = " pass[1][2011-08-21][total_passes]";
string matching = #"\[(.*?)\]";
Regex reg = new Regex(matching);
MatchCollection matches = reg.Matches(str1);
you can use foreach for matched strings.

Categories