JavaScript regular expression match - javascript

Consider the following:
var params = location.search.match(/=([\w\d-]+)&?/g);
console.log(params);
The output is:
["=7&", "=31500&", "=1"]
I don't wont any signs there, digits or words only, so I've set parentheses, but it doesn't work. So how do I do it?

Are you getting the querystring parameter? I think this is what you want (although it doesn't use regular expression).
<script type="text/javascript">
<!--
function querySt(ji) {
hu = window.location.search.substring(1);
gy = hu.split("&");
for (i=0;i<gy.length;i++) {
ft = gy[i].split("=");
if (ft[0] == ji) {
return ft[1];
}
}
}
var koko = querySt("koko");
document.write(koko);
document.write("<br>");
document.write(hu);
-->
</script>
Reference: http://ilovethecode.com/Javascript/Javascript-Tutorials-How_To-Easy/Get_Query_String_Using_Javascript.shtml

There's a nice javascript function called gup() which makes this sort of thing simple. Here's the function:
function gup( name )
{
name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
var regexS = "[\\?&]"+name+"=([^&#]*)";
var regex = new RegExp( regexS );
var results = regex.exec( window.location.href );
if( results == null )
return "";
else
return results[1];
}
and sample usage:
var myVar = gup('myVar');
So, if your querystring looks like this: ?myVar=asdf
myVar will return 'asdf'.

The .match method returns the whole matched string, not any groupings you have defined with parenthesis.
If you want to return just a grouping in a regular expression, you'll have to use the .exec method multiple times, and extract the matched group from the resulting array:
var search = location.search,
param = /=([\w\d-]+)&?/g,
params = [],
match;
while ((match = param.exec(search)) != null) {
params.push(match[1]);
}
console.log(params);
This works because the g flag is used on the regular expression. Every time you call .exec on the param regular expression, it's lastIndex attribute is set to the next matching substring and that in turn makes sure that the next call to .exec starts searching at the next match. The resulting array contains the whole matched string at index 0, then every matched group at subsequent positions. Your group is thus returned as index 1 of the array.

Related

match regular expression - JavaScript

So I have the following url:
var oURL = "https://graph.facebook.com/#{username}/posts?access_token=#{token}";
I want to take username and token out of it;
I tried:
var match = (/#\{(.*?)\}/g.exec(oURL));
console.log(match);
but it is giving me:
["#{username}", "username", index: 27, input: "https://graph.facebook.com/#{username}/posts?access_token=#{token}"
Why isn't catching token?
Thanks
The problem is that exec only returns the first match from the given index whenever called.
Returns
If the match succeeds, the exec() method returns an array and updates
properties of the regular expression object. The returned array has
the matched text as the first item, and then one item for each
capturing parenthesis that matched containing the text that was
captured.
If the match fails, the exec() method returns null.
You would need to loop, continuously matching again to find all the matches.
var matches = [],
match,
regex = /#\{(.*?)\}/g,
oURL = "https://graph.facebook.com/#{username}/posts?access_token=#{token}";
while (match = regex.exec(oURL)) {
matches.push(match)
}
console.log(matches)
However, if you are only interested in the first capture group, you can only add those to the matches array:
var matches = [],
match,
regex = /#\{(.*?)\}/g,
oURL = "https://graph.facebook.com/#{username}/posts?access_token=#{token}";
while (match = regex.exec(oURL)) {
matches.push(match[1])
}
console.log(matches)
Try this instead:
oURL.match(/#\{(.*?)\}/g)
The answer you accepted is perfect, but I thought I'd also add that it's pretty easy to create a little helper function like this:
function getMatches(str, expr) {
var matches = [];
var match;
while (match = expr.exec(str)) {
matches.push(match[1]);
}
return matches;
}
Then you can use it a little more intuitively.
var oURL = "https://graph.facebook.com/#{username}/posts?access_token=#{token}";
var expr = /#\{([^\{]*)?\}/g;
var result = getMatches(oURL, expr);
console.log(result);
http://codepen.io/Chevex/pen/VLyaeG
Try this:
var match = (/#\{(.*?)\}.*?#\{(.*?)\}/g.exec(oURL));

Return text between brackets and not include brackets

I am using the following regEx to match text in brackets:
'textA(textB)'.match(/\((.+?)\)/g)
But it returns text including the brackets e.g. (textB)
How do I return the text without the brackets e.g. textB
I assume that the input contains balanced parenthesis. If yes, then you could use the below regex to match all characters which are present within the brackets.
[^()]+(?=\))
DEMO
> 'textA(textB)'.match(/[^()]+(?=\))/g)
[ 'textB' ]
Explanation:
[^()]+ Negated character class which matches any character but not of ( or ) one or more times.
(?=\)) positive lookahead which asserts that the matched characters must be followed by a closing parenthesis )
You have to explicitly include the parentheses in the regular expression by quoting them with \
'textA(textB)'.match(/\((.+?)\)/g)
If you don't do that, the outer parentheses are interpreted as regex metacharacters.
To extract the matched text without the surrounding parentheses:
var match = 'textA(textB)'.match(/\((.+?)\)/); // no "g"
var text = match[1];
It's tricky to create a regular expression that works with the "g" ("global") qualifier to match and collect the strings within parentheses, because that qualifier causes the .match() function return value to change. Without "g", the .match() function returns an array with the overall match in position 0 and the matched groups in subsequent positions. However, with the "g", .match() simply returns all matches of the entire expression.
The only way I can think of is to repeatedly match, and the easiest way to do that (in my opinion) is with a function:
var parenthesized = [];
var text = "textA (textB) something (textC) textD) hello (last text) bye";
text.replace(/\((.+?)\)/g, function(_, contents) {
parenthesized.push(contents);
});
That will accumulate the properly-parenthesized strings "textB", "textC", and "last text" in the array. It will not include "textD" because it is not properly parenthesized.
It is possible to define a function which matches a string against a regex and customize the output array via a user-defined function.
String.prototype.matchf = function (re, fun) {
if (re == null || re.constructor != RegExp) {
re = new RegExp(re);
}
// Use default behavior of String.prototype.match for non-global regex.
if (!re.global) {
return this.match(re);
}
if (fun == null) { // null or undefined
fun = function (a) { return a[0]; };
}
if (typeof fun != "function") {
throw TypeError(fun + " is not a function");
}
// Reset lastIndex
re.lastIndex = 0;
var a;
var o = [];
while ((a = re.exec(this)) != null) {
o = o.concat(fun(a));
}
if (o.length == 0) {
o = null;
}
return o;
}
The user-defined function is supplied with an array, which is the return value of RegExp.exec.
The user-defined function is expected to return a value or an array of values. It can return an empty array to exclude the content of the current match from the resulting array.
The behavior of the custom function above should be the same as String.match when user-defined function fun is not supplied. This should have less overhead compared to abusing String.replace to extract an array, since it doesn't have to construct the replaced string.
Back to your problem, using the custom function above, you can write your code as:
'textA(textB)'.matchf(/\((.+?)\)/g, function (a) {return a[1];});
Use the matchAll function instead. Maybe?
(your original regular expression was good enough for this)
for (const results of 'textA(textB)'.matchAll(/\((.+?)\)/g)) {
console.log(results[0]) // outputs: (textB)
console.log(results[1]) // outputs: textB
}
OR
const results = [...'textA(textB)(textC)'.matchAll(/\((.+?)\)/g)];
console.log(results) // outputs array of each result
The matchAll() method returns an iterator of all results matching a string against a regular expression, including capturing groups;
index 0 returns the whole, and indexes after return group parts.

Keeping only part of a regex match

I need to search for a word in text. For this I used this regex:
var re =/duration='\d+'/ig;
var i = text.match(re);
This gives me an array of matches like "duration='300'", "duration='400'",...
I need to get only numbers. without duration=''
You can use a capturing group:
var re = /duration='(\d+)'/ig;
var match = re.exec(text);
while (match != null) {
// matched text: match[1]
match = re.exec(text);
}
Tim's answer works well (and I'm not sure why the OP says it is not what he/she wants). That said, here is another way to do it using the String.replace() method with a callback function replacement value:
function getDurations(text) {
var re =/duration='(\d+)'/ig;
var i = [];
text.replace(re, function(m0, m1){i.push(m1); return '';});
return i;
}
Note that this technique requires no loop and is quite efficient getting the job done in a single statement.

Break out of replace global loop

I have a RegExp, doing a string replace, with global set. I only need one replace, but I'm using global because there's a second set of pattern matching (a mathematical equation that determines acceptable indices for the start of the replace) that I can't readily express as part of a regex.
var myString = //function-created string
myString = myString.replace(myRegex, function(){
if (/* this index is okay */){
//!! want to STOP searching now !!//
return //my return string
} else {
return arguments[0];
//return the string we matched (no change)
//continue on to the next match
}
}, "g");
If even possible, how do I break out of the string global search?
Thanks
Possible Solution
A solution (that doesn't work in my scenario for performance reasons, since I have very large strings with thousands of possible matches to very complex RegExp running hundreds or thousands of times):
var matched = false;
var myString = //function-created string
myString = myString.replace(myRegex, function(){
if (!matched && /* this index is okay */){
matched = true;
//!! want to STOP searching now !!//
return //my return string
} else {
return arguments[0];
//return the string we matched (no change)
//continue on to the next match
}
}, "g");
Use RegExp.exec() instead. Since you only do replacement once, I make use of that fact to simplify the replacement logic.
var myString = "some string";
// NOTE: The g flag is important!
var myRegex = /some_regex/g;
// Default value when no match is found
var result = myString;
var arr = null;
while ((arr = myRegex.exec(myString)) != null) {
// arr.index gives the starting index of the match
if (/* index is OK */) {
// Assign new value to result
result = myString.substring(0, arr.index) +
/* replacement */ +
myString.substring(myRegex.lastIndex);
break;
}
// Increment lastIndex of myRegex if the regex matches an empty string
// This is important to prevent infinite loop
if (arr[0].length == 0) {
myRegex.lastIndex++;
}
}
This code exhibits the same behavior as String.match(), since it also increments the index by 1 if the last match is empty to prevent infinite loop.
You can put try-catch and use undeclared variable to exit the replace function
var i = 0;
try{
"aaaaa".replace ( /./g, function( a, b ){
//Exit the loop on the 3-rd iteration
if ( i === 3 ){
stop; //undeclared variable
}
//Increment i
i++
})
}
catch( err ){
}
alert ( "i = " + i ); //Shows 3
I question your logic about performance. I think some points made in the comments are valid. But, what do I know... ;)
However, this is one way of doing what you want. Again, I think this, performance wise, isn't the best...:
var myString = "This is the original string. Let's see if the original will change...";
var myRegex = new RegExp('original', 'g');
var matched=false;
document.write(myString+'<br>');
myString = myString.replace(myRegex, function (match) {
if ( !matched ) {
matched = true;
return 'replaced';
} else {
return match;
}
});
document.write(myString);
It's pretty much like your "Possible Solution". And it doesn't "abort" after the replace (hence my performance reservation). But it does what you asked for. It replaces the first instance, sets a flag and after that just returns the matched string.
See it work here.
Regards.

Why does this jQuery code not work?

Why doesn't the following jQuery code work?
$(function() {
var regex = /\?fb=[0-9]+/g;
var input = window.location.href;
var scrape = input.match(regex); // returns ?fb=4
var numeral = /\?fb=/g;
scrape.replace(numeral,'');
alert(scrape); // Should alert the number?
});
Basically I have a link like this:
http://foo.com/?fb=4
How do I first locate the ?fb=4 and then retrieve the number only?
Consider using the following code instead:
$(function() {
var matches = window.location.href.match(/\?fb=([0-9]+)/i);
if (matches) {
var number = matches[1];
alert(number); // will alert 4!
}
});
Test an example of it here: http://jsfiddle.net/GLAXS/
The regular expression is only slightly modified from what you provided. The global flag was removed, as you're not going to have multiple fb='s to match (otherwise your URL will be invalid!). The case insensitive flag flag was added to match FB= as well as fb=.
The number is wrapped in curly brackets to denote a capturing group which is the magic which allows us to use match.
If match matches the regular expression we specify, it'll return the matched string in the first array element. The remaining elements contain the value of each capturing group we define.
In our running example, the string "?fb=4" is matched and so is the first value of the returned array. The only capturing group we have defined is the number matcher; which is why 4 is contained in the second element.
If you all you need is to grab the value of fb, just use capturing parenthesis:
var regex = /\?fb=([0-9]+)/g;
var input = window.location.href;
var tokens = regex.exec(input);
if (tokens) { // there's a match
alert(tokens[1]); // grab first captured token
}
So, you want to feed a querystring and then get its value based on parameters?
I had had half a mind to offer Get query string values in JavaScript.
But then I saw a small kid abusing a much respectful Stack Overflow answer.
// Revised, cooler.
function getParameterByName(name) {
var match = RegExp('[?&]' + name + '=([^&]*)')
.exec(window.location.search);
return match ?
decodeURIComponent(match[1].replace(/\+/g, ' '))
: null;
}
And while you are at it, just call the function like this.
getParameterByName("fb")
How about using the following function to read the query string parameter in JavaScript:
function getQuerystring(key, default_) {
if (default_==null)
default_="";
key = key.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
var regex = new RegExp("[\\?&]"+key+"=([^&#]*)");
var qs = regex.exec(window.location.href);
if(qs == null)
return default_;
else
return qs[1];
}
and then:
alert(getQuerystring('fb'));
If you are new to Regex, why not try Program that illustrates the ins and outs of Regular Expressions

Categories