Regex to validate and extract data from a calculation - javascript

I am trying to find out a regular expression where I can validate the input and also extract required information from input.
My input contains a simple calculation like addition, subtraction, multiplication and division.
For example: if input is addtion say 7.01+9.05
var input = '7.01+9.05';
var pattern = /^-?\d+\.?\d+[-+*\/]-?\d+\.?\d+$/
var sign;
if (input.match(pattern)) {
var matches = pattern.exec(input);
var left = // logic to extract value 7.01 using matches variable;
var right = // logic to extract value 9.05 using matches variable;
var sing = // logic to extract symbol + using matches variable;
}
I have used the regular expression which I found from this post : Calculator Regular Expression with decimal point and minus sign
Can you please help me how to extract the required data in above code?

In your pattern ^-?\d+\.?\d+[-+*\/]-?\d+\.?\d+$ you want to match an optional dot using \d+\.?\d+ which works but now the minimum number of digits to match is 2 due to matching 2 times 1 or more digits using \d+ so 1+1 would not match.
What you could do if it are only simple calculations, you could use 3 capturing groups and match a digit with an optional decimal part using ?\d+(?:\.\d+)?
Your pattern might look like:
^(-?\d+(?:\.\d+)?)([-+*\/])(-?\d+(?:\.\d+)?)$
Explanation
^ Start of string
(-?\d+(?:\.\d+)?) Capture group 1, match 1+ digits with an optional decimal part
([-+*\/]) Capture group 2, match any of the listed in the character class
(-?\d+(?:\.\d+)?) Capture group 2, match 1+ digits with an optional decimal part
$ End of string
See the regex101 demo
For example
var regex = /^(-?\d+(?:\.\d+)?)([-+*\/])(-?\d+(?:\.\d+)?)$/;
[
"21+22",
"7.01+9.05",
"1-1",
"1*1",
"0*1000000",
"8/4"
].forEach(x => {
var res = x.match(regex);
var left = res[1];
var right = res[2];
var sing = res[3];
console.log(left, right, sing);
});

Sure!
You should define capture groups in your regex expression using () and |. It is important define a flag global to your regex to capture all groups.
There are 3 things you need to capture:
the left number -> ^-?\d+\.?\d+
the sign -> [-+*\/]
the right number -> -?\d+\.?\d+$
You should use | alternation to regex use the capturing groups like a or statement beetwen the groups.
The final regex will be:
var pattern = /(^-?\d+\.?\d+)|([-+*\/])|(-?\d+\.?\d+$)/g
The ouput result will be an array where the first position will be the left number, second position the sign and the third position a right number.
Therefore the rest of your code will looks like that:
if (input.match(pattern)) {
var matches = input.match(pattern); \\ I recommend use input.match here too
var left = matches[0];
var right = matches[2];
var sing = matches[1];
}

You can do that using split()
var input = '7.01+9.05';
var pattern = /^-?\d+\.?\d+[-+*\/]-?\d+\.?\d+$/
if (input.match(pattern)) {
var matches = pattern.exec(input)[0].split(/(\+|-|\*|\/)/);
var left = matches[0];
var right = matches[2];
var sign = matches[1];
console.log(left,sign,right);
}

Related

Extract a part of a regex name

Examples of filenames
FDIP_en-gb-nn_Text_v1_YYYYMMDD_SequenceNumber.txt
FDIP_fr-fr-nn_Text_v1_YYYYMMDD_SequenceNumber.txt
FDIP_de-de-nn_Text_v1_YYYYMMDD_SequenceNumber.txt
REGEX is FDIP_([a-z]{2}-[A-Z]{2}-[a-z]{2})_Text_v1_[0-9]{8}_[0-9]{14}.txt
The only part I need is the translation code which is 'en-gb', 'fr-fr' , 'de-de.
How do I extract just that part of the filename?
Modified the regex little bit to match the numbers and text. You can play around here
Explanation
to capture a group you need to wrap the regex into () this will capture as a group.
to do the named capturing you can (?<name_of_group>) and then you can access by name.
Here goes the matching process.
[a-z]{2} match 2 char from a-z
[a-zA-Z0-9] match any char of a-z or A-Z or 0-9
g means global flag i.e. match all.
i means ignore case.
var r = /FDIP_([a-z]{2}-[A-Z]{2})-[a-z]{2}_Text_v1_[0-9A-Z]{8}_[A-Z0-9]{14}.txt/gi;
let t = 'FDIP_en-gb-nn_Text_v1_YYYYMMDD_SequenceNumber.txt';
let dd = r.exec(t);
console.log(dd[1]);
This is example of group capturing
See the name in the regex and the object destructing name is matching.
const { groups: { language } } = /FDIP_(?<language>[a-z]{2}-[A-Z]{2})-[a-z]{2}_Text_v1_[0-9A-Z]{8}_[A-Z0-9]{14}.txt/gi.exec('FDIP_en-gb-nn_Text_v1_YYYYMMDD_SequenceNumber.txt');
console.log(language);
To solve your problem, you should:
Fix your regex:
FDIP_([a-z]{2}-[A-Z]{2}-[a-z]{2})_Text_v1_[0-9]{8}_[0-9]{14}.txt
// to
FDIP_([a-z]{2}-[a-z]{2})-[a-z]{2}_Text_v1_[0-9]{8}_[0-9]{14}.txt
Use get value from first group by using regex.exec function
const fileNames = [
'FDIP_en-gb-nn_Text_v1_20190101_12345678901234.txt',
'FDIP_fr-fr-nn_Text_v1_20200202_12345678901234.txt',
'FDIP_de-de-nn_Text_v1_20180808_12345678901234.txt']
const cultureNames = fileNames.map(name => {
const matched = /FDIP_([a-z]{2}-[a-z]{2})-[a-z]{2}_Text_v1_[0-9]{8}_[0-9]{14}.txt/.exec(name)
return matched && matched[1]
})
console.log(cultureNames)
Change FDIP_([a-z]{2}-[A-Z]{2}-[a-z]{2})_Text_v1_[0-9]{8}_[0-9]{14}.txt
to
let pattern = /FDIP_([a-z]{2}-[a-z]{2})-[a-z]{2}_Text_v1_[\w]{8}_[\w]{14}.txt/;
var str = 'FDIP_en-gb-nn_Text_v1_YYYYMMDD_SequenceNumber.txt';
console.log(str.match(pattern)[1]);

Getting strings between certain string and a special character

I am trying to get data between string and special character.
How can I do this in JS?
Below is my code:
var string = '(CATCH: dummy)';
var TitleRegex = /\((CATCH:.*?)\)/;
var titleData = string.match(TitleRegex);
Output should be : dummy
You could possibly fix the current expression by moving the opening ( to the location right after :, /\(CATCH:(.*?)\)/, and then grabbing Group 1 value using something like var titleData = string.match(TitleRegex)[1].
I'd suggest a bit more precise pattern here:
var string = '(CATCH: dummy)';
var TitleRegex = /\(CATCH:\s*([^()]*)\)/;
var titleData = string.match(TitleRegex);
if (titleData) {
console.log(titleData[1]);
}
The regex is \(CATCH:\s*([^()]*)\):
\(CATCH: - a (CATCH: substring
\s* - 0+ whitespaces
([^()]*) - Capturing group 1: any 0 or more chars other than ( and )
\) - a ) char.
You may actually use /\(CATCH:([^()]*)\)/ (without \s*) and just use titleData[1].trim() to get rid of any eventual whitespace on both ends of the required value.

I need help getting the first n characters of a string up to when a number character starts

I'm working with a string where I need to extract the first n characters up to where numbers begin. What would be the best way to do this as sometimes the string starts with a number: 7EUSA8889er898 I would need to extract 7EUSA But other string examples would be SWFX74849948, I would need to extract SWFX from that string.
Not sure how to do this with regex my limited knowledge is blocking me at this point:
^(\w{4}) that just gets me the first four characters but I don't really have a stopping point as sometimes the string could be somelongstring292894830982 which would require me to get somelongstring
Using \w will match a word character which includes characters and digits and an underscore.
You could match an optional digit [0-9]? from the start of the string ^and then match 1+ times A-Za-z
^[0-9]?[A-Za-z]+
Regex demo
const regex = /^[0-9]?[A-Za-z]+/;
[
"7EUSA8889er898",
"somelongstring292894830982",
"SWFX74849948"
].forEach(s => console.log(s.match(regex)[0]));
Can use this regex code:
(^\d+?[a-zA-Z]+)|(^\d+|[a-zA-Z]+)
I try with exmaple and good worked:
1- somelongstring292894830982 -> somelongstring
2- 7sdfsdf5456 -> 7sdfsdf
3- 875werwer54556 -> 875werwer
If you want to create function where the RegExp is parametrized by n parameter, this would be
function getStr(str,n) {
var pattern = "\\d?\\w{0,"+n+"}";
var reg = new RegExp(pattern);
var result = reg.exec(str);
if(result[0]) return result[0].substr(0,n);
}
There are answers to this but here is another way to do it.
var string1 = '7EUSA8889er898';
var string2 = 'SWFX74849948';
var Extract = function (args) {
var C = args.split(''); // Split string in array
var NI = []; // Store indexes of all numbers
// Loop through list -> if char is a number add its index
C.map(function (I) { return /^\d+$/.test(I) === true ? NI.push(C.indexOf(I)) : ''; });
// Get the items between the first and second occurence of a number
return C.slice(NI[0] === 0 ? NI[0] + 1 : 0, NI[1]).join('');
};
console.log(Extract(string1));
console.log(Extract(string2));
Output
EUSA
SWFX7
Since it's hard to tell what you are trying to match, I'd go with a general regex
^\d?\D+(?=\d)

getting values from a string using regular expression

Could anyone help me with this regular expression issue?
expr = /\(\(([^)]+)\)\)/;
input = ((111111111111))
the one I would need to be working is = ((111111111111),(222222222),(333333333333333))
That expression works fine to get 111111 from (input) , but not when there are also the groups 2222... and 3333.... the input might be variable by variable I mean could be ((111111111111)) or the one above or different (always following the same parenthesis pattern though)
Is there any reg expression to extract the values for both cases to an array?
The result I would like to come to is:
[0] = "111111"
[1] = "222222"
[2] = "333333"
Thanks
If you are trying to validate format while extracting desired parts you could use sticky y flag. This flag starts match from beginning and next match from where previous match ends. This approach needs one input string at a time.
Regex:
/^\(\(([^)]+)\)|(?!^)(?:,\(([^)]+)\)|\)$)/yg
Breakdown:
^\(\( Match beginning of input and immedietly ((
( Start of capturing group #1
[^)]+ Match anything but )
)\) End of CG #1, match ) immediately
| Or
(?!^) Next patterns shouldn't start at beginning
(?: Start of non-capturing group
,\(([^)]+)\) Match a separetd group (capture value in CG #2, same pattern as above)
| Or
\)$ Match ) and end of input
) End of group
JS code:
var str = '((111111111111),(222222222),(333333333333333))';
console.log(
str.replace(/^\(\(([^)]+)\)|(?!^)(?:,\(([^)]+)\)|\)$)/yg, '$1$2\n')
.split(/\n/).filter(Boolean)
);
You can replace brackes with , split it with , and then use substring to get the required number of string characters out of it.
input.replace(/\(/g, '').replace(/\)/g, '')
This will replace all the ( and ) and return a string like
111111111111,222222222,333333333333333
Now splitting this string with , will result into an array to what you want
var input = "((111111111111),(222222222),(333333333333333))";
var numbers = input.replace(/\(/g, '').replace(/\)/g, '')
numbers.split(",").map(o=> console.log(o.substring(0,6)))
If the level of nesting is fixed, you can just leave out the outer () from the pattern, and add the left parentheses to the [^)] group:
var expr = /\(([^()]+)\)/g;
var input = '((111111111111),(222222222),(333333333333333))';
var match = null;
while(match = expr.exec(input)) {
console.log(match[1]);
}

Regex text/number extraction

Below is regex code for getting the number 6 from my tesetstr. How can i extract the string 'months' from teststr using regex ?
var teststr = '6 months';
var num = /(\d+)\s*month/;
var days = teststr.match(num)[1];
console.log(days);
Currently, (\d+) matches one or more digits capturing them into Group 1 (note you are not using the group at all, so, it is redundant).
You seem to want to only match digits before a space + "month". Use the following regex:
var num = /(\d+)\s*month/;
and then access the captured value with
var days = ($('#infra_time_threshold').text()).match(num)[1] * 30;
^^^
Alternatively, you could use a lookahead right after \d+:
var num = /\d+(?=\s*month)/;
and then just use your .match(num)[0] since Group 0 value will be the whole match.
NOTE: You might want to add a null check before accessing the 0th or 1st index of the match object.

Categories