Extracting an array of integers using a regular expression in javascript - javascript

I'm having real difficulty with this but I'm no javascript expert. All I want to do is get myself an array of all matches in a string which match a given regExp. The regExp being this :
[0-9]+
ie. Any integer.
So If I pass the string "12 09:8:76:::54 12" I should get
arr[0]="12"
arr[1]="09"
arr[2]="8"
arr[3]="76"
arr[4]="54"
arr[5]="12"
Easy? Not for me! I could do this in vb.net no problem with regexp.matches(string) (something like that anyway). I thought that the javascript method .exec would also give me an array however it only returns the first match. What's going on? Code...
function testIt(){
splitOutSelection2("123:::45 0::12312 12:17");
}
function splitOutSelection2(sSelection){
var regExp = new RegExp("[0-9]+","g");
var arr = regExp.exec(sSelection);
};

arr = sSelection.match(/[0-9]+/g);
should do.
g is the global modifier that you need to get all the matches, not just the first one.

something like:
var arrMatch = "12 09:8:76:::54 12".match(/[0-9]+/g);
alert(arrMatch);
.match will return an array if global is set (and matches are found of course).
[0-9]+ means it will search for not only single digits, but also match 12, 09, 76.

According to the doc, exec return the first match. You should use match instead.
var arr = sSelection.match(/[0-9]+/g);
or
var arr = sSelection.match(/\d+/g);

All the answers work but I was wanting to keep my regExp object rather than specify it at the time of use. So simply changing the function to...
function splitOutSelection2(sSelection){
var regExp = new RegExp("[0-9]+","g");
var arr = sSelection.match(regExp);
};
..is what I was looking for. Thanks for pointing me in the right direction though to all who have replied.

function splitOutSelection2(sSelection){
return sSelection.split(/[^0-9]+/g);
};
Negate the regExp and use String#split.

Related

Regexp group not excluding dots

Let's say I have the following string: div.classOneA.classOneB#idOne
Trying to write a regexp which extracts the classes (classOneA, classOneB) from it. I was able to do this but with Lookbehind assertion only.
It looks like this:
'div.classOneA.classOneB#idOne'.match(/(?<=\.)([^.#]+)/g)
> (2) ["classOneA", "classOneB"]
Now I would like to archive this without the lookbehind approach and do not really understand why my solution's not working.
'div.classOneA.classOneB#idOne'.match(/\.([^.#]+)/g)
> (2) [".classOneA", ".classOneB"]
Thought that the grouping will solve my problem but all matching item contains the dot as well.
There isn't a good way in Javascript to both match multiple times (/g option) and pick up capture groups (in the parens). Try this:
var input = "div.classOneA.classOneB#idOne";
var regex = /\.([^.#]+)/g;
var matches, output = [];
while (matches = regex.exec(input)) {
output.push(matches[1]);
}
This is because with g modifier you get all matching substrings but not its matching groups (that is as if (...) pairs worked just like (?:...) ones.
You see. Whithout g modifier:
> 'div.classOneA.classOneB#idOne'.match(/\.([^.#]+)/)
[ '.classOneA',
'classOneA',
index: 3,
input: 'div.classOneA.classOneB#idOne',
groups: undefined ]
With g modifier:
> 'div.classOneA.classOneB#idOne'.match(/\.([^.#]+)/g)
[ '.classOneA', '.classOneB' ]
In other words: you obtain all matches but only the whole match (0 item) per each.
There are many solutions:
Use LookBehind assertions as you pointed out yourself.
Fix each result later adding .map(x=>x.replace(/^\./, ""))
Or, if your input structure won't be much more complicated than the example you provide, simply use a cheaper approach:
> 'div.classOneA.classOneB#idOne'.replace(/#.*/, "").split(".").slice(1)
[ 'classOneA', 'classOneB' ]
Use .replace() + callback instead of .match() in order to be able to access capture groups of every match:
const str = 'div.classOneA.classOneB#idOne';
const matches = [];
str.replace(/\.([^.#]+)/g, (...args)=>matches.push(args[1]))
console.log(matches); // [ 'classOneA', 'classOneB' ]
I would recommend the third one (if there aren't other possible inputs that could eventually break it) because it is much more efficient (actual regular expressions are used only once to trim the '#idOne' part).
If you want to expand you regex. you can simply map on results and replace . with empty string
let op = 'div.classOneA.classOneB#idOne'.match(/\.([^.#]+)/g)
.map(e=> e.replace(/\./g,''))
console.log(op)
If you know you are searching for a text containing class, then you can use something like
'div.classOneA.classOneB#idOne'.match(/class[^.#]+/g)
If the only thing you know is that the text is preceded by a dot, then you must use lookbehind.
This regex will work without lookbehind assertion:
'div.classOneA.classOneB#idOne'.match(/\.[^\.#]+/g).map(item => item.substring(1));
Lookbehind assertion is not available in JavaScript recently.
I'm not an expert on using regex - particularly in Javascript - but after some research on MDN I've figured out why your attempt wasn't working, and how to fix.
The problem is that using .match with a regexp with the /g flag will ignore capturing groups. So instead you have to use the .exec method on the regexp object, using a loop to execute it multiple times to get all the results.
So the following code is what works, and can be adapted for similar cases. (Note the grp[1] - this is because the first element of the array returned by .exec is the entire match, the groups are the subsequent elements.)
var regExp = /\.([^.#]+)/g
var result = [];
var grp;
while ((grp = regExp.exec('div.classOneA.classOneB#idOne')) !== null) {
result.push(grp[1]);
}
console.log(result)

JS Regex: how to remove first 2 zero's from "08/08/2017"

I'm new to regex, and have been researching all night how to remove the first 2 zeros from a string like "08/08/2017" (without removing 0 in "2017")
The 5+ regex tutorials I've reviewed do not seem to cover what I need here.
The date could be any sysdate returned from the system. So the regex also needs to work for "12/12/2017"
Here is the best I have come up with:
let sysdate = "08/08/2017"
let todayminuszero = str.replace("0","");
let today = todayminus0.replace("0","");
It works, but obviously it's unprofessional.
From the tutorials, I'm pretty sure I can do something along the lines of this:
str.replace(/\d{2}//g,""),);
This pattern would avoid getting the 3rd zero in str.
Replacement String would have to indicate 8/8/
Not sure how to write this though.
For date manipulation I would use other functions(best date related) but, this should do it, for the case that you stated. If you need other formats or so, I would suggest removing the zeros in an different way, but It all depends on you UseCase.
let sysdate = "08/08/2017";
let todayminuszero = sysdate.replace(/0(?=\d\/)/gi,"");
console.info(todayminuszero);
(?= ... ) is called Lookahead and with this you can see what is there, without replacing it
in this case we are checking for a number and a slash. (?=\d\/)
here some more information, if you want to read about lookahead and more http://www.regular-expressions.info/lookaround.html
A good place to test regex expressions is https://regex101.com/
I always use this for more advance expressions, since it displays all matching groups and so, with a great explaination. Great resource/help, if you are learning or creating difficult Expressions.
Info: as mentioned by Rajesh, the i flag is not needed for this Expression, I just use it out of personal preference. This flag just sets the expression-match to case insensitive.
-- Out of Scope, but may be interesting --
A longer solution without regex could look like this:
let sysdate = "08/08/2017";
let todayminuszero = sysdate.split("/").map(x => parseInt(x)).join("/");
console.info(todayminuszero);
Backside, this solution has many moving parts, the split function to make an array(´"08/08/2017"´ to ´["08", "08", "2017"]´), the map function, with a lambda function => and the parseInt function, to make out of each string item a nice integer (like: "08" to 8, ... ) and at last the join function that creates the final string out of the newly created integer array.
you should use this
let sysdate = "08/08/2017"
let todayminuszero = sysdate.replace(/(^|\/)0/g,"$1");
console.log(todayminuszero);
function stripLeadingZerosDate(dateStr){
return dateStr.split('/').reduce(function(date, datePart){
return date += parseInt(datePart) + '/'
}, '').slice(0, -1);
}
console.log(stripLeadingZerosDate('01/02/2016'));
console.log(stripLeadingZerosDate('2016/02/01'));
look at here
function stripLeadingZerosDate(dateStr){
return dateStr.split('/').reduce(function(date, datePart){
return date += parseInt(datePart) + '/'
}, '').slice(0, -1);
}
console.log(stripLeadingZerosDate('01/02/2016'));// 1/2/2016
console.log(stripLeadingZerosDate('2016/02/01'));// "2016/2/1"
By first 2 zeros, I understand you mean zero before 8 in month and in date.
You can try something like this:
Idea
Create a regex that captures group of number representing date, month and year.
Use this regex to replace values.
Use a function to return processed value.
var sysdate = "08/08/2017"
var numRegex = /(\d)+/g;
var result = sysdate.replace(numRegex, function(match){
return parseInt(match)
});
console.log(result)

JS how do I select a string from between two special characters?

I have a string that will be formatted something like ___<test#email.com>____ where the underscores is irrelevant stuff I don't need but varys in length. I need to select and store what is between the brackets.
My problem is that all of the sub string solutions I have seen operate off of a hard integer location in the string. But the start and end of the substring I want to select (the brackets) will never be the same.
So I thought if I could use something to find the location of the brackets then feed that to a substring solution that would work. But all of the ways I have found of identifying special characters only reports if there are special characters, not where they are.
Thanks in advance!
based on this answer
var text = '___<test#email.com>____';
var values = text.split(/[<>]+/);
console.log(values); // your values should be at indexes 1, 3, 5, etc...
Here's a regex that should set you on your way.
let string = "asdf asdf asdf as <thing#stuff.com> jl;kj;l kj ;lkj ;lk j;lk";
let myMatches = string.match(/<.*>/g);
let myMatch = myMatches[0].slice(1).slice(0,-1);
The .match function returns an array of matches, so you can find multiple <stuff> entries.
There's probably a way to do it without the slicing, but that's all I've got for now.
With Regex:
var myRe = /<(.*)>/g;
var myArray = myRe.exec("____<asdf>___");
if (myArray)
console.log(myArray[1]);
Regex test here
JSFiddle test here

How can I inverse matched result of the pattern?

Here is my string:
Organization 2
info#something.org.au more#something.com market#gmail.com single#noidea.com
Organization 3
headmistress#money.com head#skull.com
Also this is my pattern:
/^.*?#[^ ]+|^.*$/gm
As you see in the demo, the pattern matches this:
Organization 2
info#something.org.au
Organization 3
headmistress#money.com
My question: How can I make it inverse? I mean I want to match this:
more#something.com market#gmail.com single#noidea.com
head#skull.com
How can I do that? Actually I can write a new (and completely different) pattern to grab expected result, but I want to know, Is "inverting the result of a pattern" possible?
No, I don't believe there is a way to directly inverse a Regular Expression but keeping it the same otherwise.
However, you could achieve something close to what you're after by using your existing RegExp to replace its matches with an empty string:
var everythingThatDidntMatchStr = str.replace(/^.*?#[^ ]+|^.*$/gm, '');
You can replace the matches from first RegExp by using Array.prototype.forEach() to replace matched RegExp with empty string using `String.ptototype.replace();
var re = str.match(/^.*?#[^ ]+|^.*$/gm);
var res = str;
re.forEach(val => res = res.replace(new RegExp(val), ""));

RegExp.test not working?

I am trying to validate year using Regex.test in javascript, but no able to figure out why its returning false.
var regEx = new RegExp("^(19|20)[\d]{2,2}$");
regEx.test(inputValue) returns false for input value 1981, 2007
Thanks
As you're creating a RegExp object using a string expression, you need to double the backslashes so they escape properly. Also [\d]{2,2} can be simplified to \d\d:
var regEx = new RegExp("^(19|20)\\d\\d$");
Or better yet use a regex literal to avoid doubling backslashes:
var regEx = /^(19|20)\d\d$/;
Found the REAL issue:
Change your declaration to remove quotes:
var regEx = new RegExp(/^(19|20)[\d]{2,2}$/);
Do you mean
var inputValue = "1981, 2007";
If so, this will fail because the pattern is not matched due to the start string (^) and end string ($) characters.
If you want to capture both years, remove these characters from your pattern and do a global match (with /g)
var regEx = new RegExp(/(?:19|20)\d{2}/g);
var inputValue = "1981, 2007";
var matches = inputValue.match(regEx);
matches will be an array containing all matches.
I've noticed, for reasons I can't explain, sometimes you have to have two \\ in front of the d.
so try [\\d] and see if that helps.

Categories