Regex: .exec() function not returning expected output - javascript

This doesn't return what I, or regex101, expects:
var myString = "Accel World|http://www.anime-planet.com/anime/accel-worldAh! My Goddess|http://www.anime-planet.com/anime/ah-my-goddess";
var reg = /[^|]*/g;
var regResponse = reg.exec(myString);
console.log(regResponse);
according to regex101, this should match everything except '|' and return it yet it only matches the first string, Accel World, as opposed to everything but '|'.
How do I fix this?

Exec will only return one result at a time (subsequent calls will return the rest, but you also need to use the + instead of *)
You could use the myString.match(reg) htough to get all results in one go.
var myString = "Accel World|http://www.anime-planet.com/anime/accel-worldAh! My Goddess|http://www.anime-planet.com/anime/ah-my-goddess";
var reg = /[^|]+/g;
var regResponse = myString.match(reg);
console.log(regResponse);

You need to loop .exec() to retrieve all matches. The documentation says
If your regular expression uses the "g" flag, you can use the exec()
method multiple times to find successive matches in the same string.
var reg = /[^|]+/g;
while(regResponse = reg.exec(myString)) {
console.log(regResponse);
}

Try a "+" instead of the "*"
So,
var reg = /[^|]+/g;

Related

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)

Regex extracting multiple matches for string [duplicate]

I'm trying to obtain all possible matches from a string using regex with javascript. It appears that my method of doing this is not matching parts of the string that have already been matched.
Variables:
var string = 'A1B1Y:A1B2Y:A1B3Y:A1B4Z:A1B5Y:A1B6Y:A1B7Y:A1B8Z:A1B9Y:A1B10Y:A1B11Y';
var reg = /A[0-9]+B[0-9]+Y:A[0-9]+B[0-9]+Y/g;
Code:
var match = string.match(reg);
All matched results I get:
A1B1Y:A1B2Y
A1B5Y:A1B6Y
A1B9Y:A1B10Y
Matched results I want:
A1B1Y:A1B2Y
A1B2Y:A1B3Y
A1B5Y:A1B6Y
A1B6Y:A1B7Y
A1B9Y:A1B10Y
A1B10Y:A1B11Y
In my head, I want A1B1Y:A1B2Y to be a match along with A1B2Y:A1B3Y, even though A1B2Y in the string will need to be part of two matches.
Without modifying your regex, you can set it to start matching at the beginning of the second half of the match after each match using .exec and manipulating the regex object's lastIndex property.
var string = 'A1B1Y:A1B2Y:A1B3Y:A1B4Z:A1B5Y:A1B6Y:A1B7Y:A1B8Z:A1B9Y:A1B10Y:A1B11Y';
var reg = /A[0-9]+B[0-9]+Y:A[0-9]+B[0-9]+Y/g;
var matches = [], found;
while (found = reg.exec(string)) {
matches.push(found[0]);
reg.lastIndex -= found[0].split(':')[1].length;
}
console.log(matches);
//["A1B1Y:A1B2Y", "A1B2Y:A1B3Y", "A1B5Y:A1B6Y", "A1B6Y:A1B7Y", "A1B9Y:A1B10Y", "A1B10Y:A1B11Y"]
Demo
As per Bergi's comment, you can also get the index of the last match and increment it by 1 so it instead of starting to match from the second half of the match onwards, it will start attempting to match from the second character of each match onwards:
reg.lastIndex = found.index+1;
Demo
The final outcome is the same. Though, Bergi's update has a little less code and performs slightly faster. =]
You cannot get the direct result from match, but it is possible to produce the result via RegExp.exec and with some modification to the regex:
var regex = /A[0-9]+B[0-9]+Y(?=(:A[0-9]+B[0-9]+Y))/g;
var input = 'A1B1Y:A1B2Y:A1B3Y:A1B4Z:A1B5Y:A1B6Y:A1B7Y:A1B8Z:A1B9Y:A1B10Y:A1B11Y'
var arr;
var results = [];
while ((arr = regex.exec(input)) !== null) {
results.push(arr[0] + arr[1]);
}
I used zero-width positive look-ahead (?=pattern) in order not to consume the text, so that the overlapping portion can be rematched.
Actually, it is possible to abuse replace method to do achieve the same result:
var input = 'A1B1Y:A1B2Y:A1B3Y:A1B4Z:A1B5Y:A1B6Y:A1B7Y:A1B8Z:A1B9Y:A1B10Y:A1B11Y'
var results = [];
input.replace(/A[0-9]+B[0-9]+Y(?=(:A[0-9]+B[0-9]+Y))/g, function ($0, $1) {
results.push($0 + $1);
return '';
});
However, since it is replace, it does extra useless replacement work.
Unfortunately, it's not quite as simple as a single string.match.
The reason is that you want overlapping matches, which the /g flag doesn't give you.
You could use lookahead:
var re = /A\d+B\d+Y(?=:A\d+B\d+Y)/g;
But now you get:
string.match(re); // ["A1B1Y", "A1B2Y", "A1B5Y", "A1B6Y", "A1B9Y", "A1B10Y"]
The reason is that lookahead is zero-width, meaning that it just says whether the pattern comes after what you're trying to match or not; it doesn't include it in the match.
You could use exec to try and grab what you want. If a regex has the /g flag, you can run exec repeatedly to get all the matches:
// using re from above to get the overlapping matches
var m;
var matches = [];
var re2 = /A\d+B\d+Y:A\d+B\d+Y/g; // make another regex to get what we need
while ((m = re.exec(string)) !== null) {
// m is a match object, which has the index of the current match
matches.push(string.substring(m.index).match(re2)[0]);
}
matches == [
"A1B1Y:A1B2Y",
"A1B2Y:A1B3Y",
"A1B5Y:A1B6Y",
"A1B6Y:A1B7Y",
"A1B9Y:A1B10Y",
"A1B10Y:A1B11Y"
];
Here's a fiddle of this in action. Open up the console to see the results
Alternatively, you could split the original string on :, then loop through the resulting array, pulling out the the ones that match when array[i] and array[i+1] both match like you want.

Passing Parameter into function match

I am using the function match for a search engine, so whenever a user types a search-string I take that string and use the match function on an array containing country names, but it doesn't seem to work.
For example if I do :
var string = "algeria";
var res = string.match(/alge/g); //alge is what the user would have typed in the search bar
alert(res);
I get a string res = "alge": //thus verifying that alge exists in algeria
But if I do this, it returns null, why? and how can I make it work?
var regex = "/alge/g";
var string = "algeria";
var res = string.match(regex);
alert(res);
To make a regex from a string, you need to create a RegExp object:
var regex = new RegExp("alge", "g");
(Beware that unless your users will be typing actual regular expressions, you'll need to escape any characters that have special meaning within regular expressions - see Is there a RegExp.escape function in Javascript? for ways to do this.)
You don't need quotes around the regex:
var regex = /alge/g;
Remove the quotes around the regex.
var regex = /alge/g;
var string = "algeria";
var res = string.match(regex);
alert(res);
found the answer, the match function takes a regex object so have to do
var regex = new RegExp(string, "g");
var res = text.match(regex);
This works fine

Regex working fine in C# but not in Javascript

I have the following javascript code:
var markdown = "I have \(x=1\) and \(y=2\) and even \[z=3\]"
var latexRegex = new RegExp("\\\[.*\\\]|\\\(.*\\\)");
var matches = latexRegex.exec(markdown);
alert(matches[0]);
matches has only matches[0] = "x=1 and y=2" and should be:
matches[0] = "\(x=1\)"
matches[1] = "\(y=2\)"
matches[2] = "\[z=3\]"
But this regex works fine in C#.
Any idea why this happens?
Thank You,
Miguel
Specify g flag to match multiple times.
Use String.match instead of RegExp.exec.
Using regular expression literal (/.../), you don't need to escape \.
* matches greedily. Use non-greedy version: *?
var markdown = "I have \(x=1\) and \(y=2\) and even \[z=3\]"
var latexRegex = /\[.*?\]|\(.*?\)/g;
var matches = markdown.match(latexRegex);
matches // => ["(x=1)", "(y=2)", "[z=3]"]
Try non-greedy: \\\[.*?\\\]|\\\(.*?\\\). You need to also use a loop if using the .exec() method like so:
var res, matches = [], string = 'I have \(x=1\) and \(y=2\) and even \[z=3\]';
var exp = new RegExp('\\\[.*?\\\]|\\\(.*?\\\)', 'g');
while (res = exp.exec(string)) {
matches.push(res[0]);
}
console.log(matches);
Try using the match function instead of the exec function. exec only returns the first string it finds, match returns them all, if the global flag is set.
var markdown = "I have \(x=1\) and \(y=2\) and even \[z=3\]";
var latexRegex = new RegExp("\\\[.*\\\]|\\\(.*\\\)", "g");
var matches = markdown.match(latexRegex);
alert(matches[0]);
alert(matches[1]);
If you don't want to get \(x=1\) and \(y=2\) as a match, you will need to use non-greedy operators (*?) instead of greedy operators (*). Your RegExp will become:
var latexRegex = new RegExp("\\\[.*?\\\]|\\\(.*?\\\)");

how do I capture something after something else? like a referer=someString

I have ref=Apple
and my current regex is
var regex = /ref=(.+)/;
var ref = regex.exec(window.location.href);
alert(ref[0]);
but that includes the ref=
now, I also want to stop capturing characters if a & is at the end of the ref param. cause ref may not always be the last param in the url.
You'll want to split the url parameters, rather than using a regular expression.
Something like:
var get = window.location.href.split('?')[1];
var params = get.split('&');
for (p in params) {
var key = params[p].split('=')[0];
var value = params[p].split('=')[1];
if (key == 'ref') {
alert('ref is ' + value);
}
}
Use ref[1] instead.
This accesses what is captured by group 1 in your pattern.
Note that there's almost certainly a better way to do key/value parsing in Javascript than regex.
References
regular-expressions.info/Brackets for Capturing
You are using the ref wrong, you should use ref[1] for the (.+), ref[0] is the whole match.
If & is at the end, modify the regexp to /ref=([^&]+)/, to exclude &s.
Also, make sure you urldecode (unescape in JavaScript) the match.
Capture only word characters and numbers:
var regex = /ref=(\w+)/;
var ref = regex.exec(window.location.href);
alert(ref[1]);
Capture word characters, numbers, - and _:
var regex = /ref=([\w_\-]+)/;
var ref = regex.exec(window.location.href);
alert(ref[1]);
More information about Regular Expressions (the basics)
try this regex pattern ref=(.*?)&
This pattern will match anything after ref= and stop before '&'
To get the value of m just use following code:
var regex = /ref=(.*?)&/;
var ref = regex.exec(window.location.href);
alert(ref[1]);

Categories

Resources