Javascript regex that matches a decimal that is polluted with other characters - javascript

I'm trying to match the first set of digits in the following examples.
some stuff (6 out of 10 as a rating)
needs to return 6
some stuff (2.3 out of 10 as a rating)
needs to return 2.3
some stuff (10 out of 10 as a rating)
needs to return 10
Also, sometimes the string won't have a number
some stuff but nothing else

var match = /\d+(\.\d+)?/.exec("some stuff (10 out of 10 as a rating)");
alert(match[0]);
\d matches any numner, 0-9
+ means 1 or more
\. matches a .
? means 0 or 1
so overall it means any number of digits (0-9) optionally followed by, a decimal point followed by 1 or more digits.
As a function:
var getFirstNumber = function(input){
var match = /\d+(\.\d+)?/.exec(input);
return match[0];
};

You can try this 'some stuff (2.3 out of 10 as a rating)'.match(/\D*(\d\.?(\d)*)/)[1]

Related

Javascript regex for money with max length

I want validate a money string with numbers max length 13 with 2 decimal. I have a comma as decimal separator and a period as a thousands separator.
I have this regex:
/^(\d{1}\.)?(\d+\.?)+(,\d{2})?$/
For sintax is valid but not for max length. What I need to add to this regex?
For example, these strings must be valid:
1.000.000.000.000
1.000.000.000.000,00
1
1,00
123,45
And these must be invalid:
10.000.000.000.000
10.000.000.000.000,00
10.000.000.000.000.000
10.000.000.000.000.000,00
Maybe try to assert position is not followed by 18 digits/dots using a negative lookahead:
^(?![\d.]{18})\d{1,3}(?:\.\d{3})*(?:,\d\d?)?$
See an online demo. Here is assumed you would also allow a single digit decimal.
^ - Open line anchor.
(?![\d.]{18}) - Negative lookahead to prevent 18 digits/dots ahead.
\d{1,3} - One-to-three digits.
(?:\.\d{3})* - A non-capture group of a literal dot followed by three digits with a 0+ multiplier.
(?:,\d\d?)? - Optional non-capture group of a comma followed by either 1 or two digits. Remove the question mark to make the 2nd decimal non-optional.
$ - End line anchor.
You may use this regex for validation:
^(?=[\d.]{1,17}(?:,\d{2})?$)\d{1,3}(?:\.\d{3})*(?:,\d{2})?$
RegEx Demo
RegEx Details:
^: Start
(?=[\d.]{1,17}(?:,\d{2})?$): Lookahead to match dot or digit 1 to 17 times followed by optional comma and 2 digits
\d{1,3}: Match 1 to 3 digits
(?:\.\d{3})*: Match . followed by 3 digits. Repeat this group 0 or more times
(?:,\d{2})?: Match optional , followed 2 decimal digits
$: End
90% of the time there is a better solution than using regex. It's probably best just to convert your strings into a real number then compare vs. your limit (ie 9999999999999.99).
// Pass a string
function convertStr(string) {
/*
Remove all '.'
Replace all ',' with '.'
*/
let numStr = string.split('.').join('').replaceAll(',', '.');
// Convert modified string into a real number
let realNum = parseFloat(numStr);
/*
if converted string is a real number...
round it to two decimal places and return it
Otherwise return false
*/
return !Number.isNaN(realNum) ? Math.round((realNum + Number.EPSILON) * 100) / 100 : false;
}
// Pass a string and the maxed number
function numLimit(string, limit) {
// Get the result of convertString()
let number = convertStr(string);
// if the result is equal to or less than limit...
if (number <= limit) {
return true;
} else {
return false;
}
}
const limit = 9999999999999.99;
const valid = ['1.000.000.000.000',
'1.000.000.000.000,00', '1', '1,00', '123,45'
];
const invalid = ['10.000.000.000.000', '10.000.000.000.000,00', '10.000.000.000.000.000', '10.000.000.000.000.000,00'];
let validResults = valid.map(str => numLimit(str, limit));
let invalidResults = invalid.map(str => numLimit(str, limit));
console.log('valid: ' + validResults);
console.log('invalid: ' + invalidResults);

Regex for numbers with spaces and + sign in front

If i want to accept only numbers then i will use this regex
^[0-9]*$
but the problem here is that the numbers like
+1 00
are not catched and my regex will show that it is invalid
The user needs to type only numbers but only one space in between is allowed and + sign at the beggining should be optional.
So acceptable is:
+1 11 1 1 11
or
1 11 1 1 11
Unacceptable is:
+1 11 1 1 11
or
1 11 1 1 11
please help
You may try using this regex pattern:
^\+?\d+(?:[ ]?\d+)*$
Sample script:
console.log(/^\+?\d+(?:[ ]?\d+)*$/.test('+1 11 1 1 11')); // true
console.log(/^\+?\d+(?:[ ]?\d+)*$/.test('1 11 1 1 11')); // true
console.log(/^\+?\d+(?:[ ]?\d+)*$/.test('+1 11 1 1 11')); // false
console.log(/^\+?\d+(?:[ ]?\d+)*$/.test('1 11 1 1 11')); // false
The regex pattern used here says to:
^ from the start of the string
\+? match an optional leading +
\d+ then match one or more digits
(?:[ ]?\d+)* followed by an optional single space and more digits,
zero or more times
$ end of the string
Close!
/^[0-9]{1,}$/g
^ = start/first character
[0-9] = Select only number 0-9 but match it once,
{1,} = Match it one or more times,
$ = look no further, so cut all spaces, letters or non matches out!
or even
/^[0-9]+$/g
or even (preferred)
/^-?[1-9]\d*\.?(\d+)?$/g
You should not match anything more but numerals.
function CheckInt(inputNum) {
if (inputNum.toString().match(/^-?[1-9]\d*\.?(\d+)?$/g)) {
console.log(`${inputNum} is a number (INT)`);
} else {
console.log(`${inputNum} is not a number (INT)`);
}
}
CheckInt("a");
CheckInt("b");
CheckInt("c");
CheckInt("102 020");
CheckInt("102-1029");
CheckInt(5400);
CheckInt(-2);
CheckInt(20);
CheckInt(2042992540);

Regex for getting only the last N numbers in javascript

I've being trying to generate a regex for this string:
case1: test-123456789 should get 56789
case2: test-1234-123456789 should get 56789
case3: test-12345 should fail or not giving anything
what I need is a way to get only the last 5 numbers from only 9 numbers
so far I did this:
case.match(/\d{5}$/)
it works for the first 2 cases but not for the last one
You may use
/\b\d{4}(\d{5})$/
See the regex demo. Get Group 1 value.
Details
\b - word boundary (to make sure the digit chunks are 9 digit long) - if your digit chunks at the end of the string can contain more, remove \b
\d{4} - four digits
(\d{5}) - Group 1: five digits
$ - end of string.
JS demo:
var strs = ['test-123456789','test-1234-123456789','test-12345'];
var rx = /\b\d{4}(\d{5})$/;
for (var s of strs) {
var m = s.match(rx);
if (m) {
console.log(s, "=>", m[1]);
} else {
console.log("Fail for ", s);
}
}
You can try this:
var test="test-123456789";
console.log((test.match(/[^\d]\d{4}(\d{5})$/)||{1: null/*default value if not found*/})[1]);
This way supports default value for when not found any matching (look at inserted comment inline above code.).
You can use a positive lookbehind (?<= ) to assert that your group of 5 digits is preceeded by a group of 4 digits without including them in the result.
/(?<=\d{4})\d{5}$/
var inputs = [
"test-123456789", // 56789
"test-1234-123456789", // 56789
"test-12345", //fail or not giving anything
]
var rgx = /(?<=\d{4})\d{5}$/
inputs.forEach(str => {
console.log(rgx.exec(str))
})

How to fetch only numbers which are not starting with 2 using regex in javascript?

I have a list of numbers like the following one:
200
302
301
201
205
500
Using regex, how can I fetch only the numbers which don't start with 2?
So the output should looks like :
302
301
500
Brief
There are multiple ways to accomplish this (presented below).
Note: I know the patterns only match the first character. Please read the entire answer to understand why (and how to match the full number if that's needed).
Code
The Usage section uses the first regex from each method (as it's a simple validation on the first character). The second regex from each method allows you to capture the entire number if that's the intention.
Method 1 - Regex: Character set
This method takes 39 steps and is 9 (+3) characters long.
See regex in use here
\b[013-9]
\b[013-9]\d*
Method 2 - Regex: Negative lookahead
This method takes 63 steps and is 9 (+1) characters long.
See regex in use here
\b(?!2)\d
\b(?!2)\d*
Method 3 - Regex: Negated character set
This method takes 39 steps and is 8 (+3) characters long.
See regex in use here
\b[^\D2]
\b[^\D2]\d*
Method 4 - JavaScript: startsWith
startsWith("2");
Method 5 - JavaScript: Array element
Assuming n is the number converted to a string.
n[0] !== "2"
Method 6 - JavaScript: Math
Assuming n is a positive number (we make it positive for the validation).
while(n >= 10) {
n = Math.floor(n/10);
}
if(n !== 2)
Usage
var nums = [200,302,301,201,205,500];
console.log("Method 1");
var r = /\b[013-9]/g
nums.forEach(function(s){
s = s.toString();
if(s.match(r)) {
console.log(s);
}
});
console.log("\nMethod 2");
var r = /\b(?!2)\d/g
nums.forEach(function(s){
s = s.toString();
if(s.match(r)) {
console.log(s);
}
});
console.log("\nMethod 3");
var r = /\b[^\D2]/g
nums.forEach(function(s){
s = s.toString();
if(s.match(r)) {
console.log(s);
}
});
console.log("\nMethod 4");
nums.forEach(function(s){
s = s.toString();
if(!s.startsWith("2")) {
console.log(s);
}
});
console.log("\nMethod 5");
nums.forEach(function(s){
s = s.toString();
if(s[0] !== "2") {
console.log(s);
}
});
console.log("\nMethod 6");
nums.forEach(function(s){
var n = Math.abs(s);
while(n >= 10) {
n = Math.floor(n/10);
}
if(n !== 2) {
console.log(s);
}
});
Results
Input
200
302
301
201
205
500
Output
302
301
500
Explanation
Note: All the regular expressions in my answer use \b (word boundary) to ensure the start of the number. You can replace this with your needs. If the input is multiline, for example, you may want to use ^ (start of line assertion) with the multiline flag (typically m). The below explanations exclude the explanation of the \b token (since I've already explained it).
Method 1 - Regex: Character set
[013-9] Match a character in the set (0, 1, or a number in the range of 3-9)
Method 2 - Regex: Negative lookahead
(?!2)\d Negative lookahead ensuring what follows is not a 2.
Method 3 - Regex: Negated character set
[^\D2] Match any character not in the set (any non-digit or 2). Note that [^\D2] is actually a double negative that means match any digit, excluding 2
Method 4 - JavaScript: startsWith
From Mozilla's documentation:
Syntax
str.startsWith(searchString[, position])
Parameters
searchString
The characters to be searched for at the start of this string.
position Optional
The position in this string at which to begin searching for searchString; defaults to 0.
Return value
true if the given characters are found at the beginning of the
string; otherwise, false.
Description
This method lets you determine whether or not a string begins with
another string. This method is case-sensitive.
Method 5 - JavaScript: Array element
This method is simply taking the first digit in a number and testing it against the string 2 to see if they match. Anything that returns false is returned (does not start with 2).
Method 6 - JavaScript: Math
This method gets the absolute value of a number Math.abs() and then continuously divides the number by 10 while removing decimal places (Math.floor(n/10)) until the number is less than 10. The result is then checked against the number 2 to ensure it doesn't match if(n !== 2).

Format a string in blocks of 3 digits

How would I go about reformating a string into blocks of 3 digits separated by dash (-) in JavaScript?
ex:
let myString = "00 64 33 3-44-23 982- 23-1-0"
produce desired output as:
myString = "006-433-344-239-822-310"
With regex:
("00 64 33 3-44-23 982- 23-1-0").replace(/\D/g,"").replace(/(\d{3})(?!$)/g,'$1-')
Explanation:
\D - remove all non numeric characters
(\d{3})(?!$)
(\d{3}) - match 3 numbers
(?!$) - but not the last 3
To turn 0 - 22 1985--324 into 022-198-53-24:
("0 - 22 1985--324")
.replace(/\D/g,"") // strip numbers
.replace( // do specific format
/^(\d{3})(\d{3})(\d{2})(\d{2})$/g,
'$1-$2-$3-$4'
)
From what you've said in the comments I believe you want groups of 3 where possible and groups of 2 at the end if there aren't enough numbers. I believe this will do it:
[
'1-2 3 45---67 890',
'12345678901',
'123456789012',
'1234567890123',
'12345678901234',
'1',
'12',
'123',
'1234',
'12345',
'123456',
'1234567'
].forEach(function(str) {
console.log(str.replace(/\D/g, '').replace(/(\d\d\d?)(?=\d\d)/g, '$1-'));
});
The /\D/g removes all the non-digits. The capture group (\d\d\d?) will attempt to grab 3 digits if it can (RegExps are greedy so they grab as much as possible) but if it can't grab 3 digits that ? makes the third digit optional. The lookahead (?=\d\d) requires there to be at least 2 more digits after the initial capture. The result of this is that if there are 5 or more digits remaining in the string this will result in 3 digits being included in the capture but if there are only 4 remaining it will apply the ? to grab just 2 digits.
When making multiple matches using the g flag the string is consumed from start to finish in one run. Each time it makes a match it doesn't go back to the start again, it just carries on. This means that matches can never overlap. Lookaheads provides a way to check what's coming up next without including it in the match, so that you can effectively rewind.
The key to understanding this RegExp is the observation that wherever we insert a - in the result there must always be at least 2 more digits after it. In English it translates as 'grab 3 digits if we can (or 2 if we can't) so long as there are 2 more digits yet to come'.
First you can use 'replace' to remove any non-digit characters with regex.
let myString = "00 64 33 3-44-23 982- 23-1-0"
myString = myString.replace(/\D/g, "")
// "006433344239822310"
Secondly, 'match' any digits (0-9) between 1 and 3 times. The match function conveniently returns an array with an item for each match.
myString = myString.match(/\d{1,3}/g)
// [006,433,344,239,822,310]
Lastly, join the array using "-" as the separator.
myString = myString.join("-");
// 006-433-344-239-822-310
And if you would like to chain each step together..
myString = myString.replace(/\D/g, "").match(/\d{1,3}/g).join("-");
Note that if the string has any leftover digits, they will be left in their own block on the end of the string. This is due to the 1-3 match.
For example..
"00 64 33 3-44-23 982- 23-1-0 24" // before - with 2 extra digits
"006-433-344-239-822-310-24" // after - the extra digits are maintained
Here's a non-regexp solution:
joinGroups(joinDigits(partition3(extract(string))))
joinGroups is just
// Join groups of digits with a hyphen.
const joinGroups = a => a.join('-');
joinDigits is easy enough too:
// Join elements of subarrays together into strings.
const joinDigits = groups = groups.map(group => group.join(''));
extract is easy too:
// Extract all digits from a string and return as array.
const extract = input => input.match(/\d/g);
partition3 is a little harder. There are many samples here on SO and elsewhere. See the implementation in the snippet for one idea.
const joinGroups = a => a.join('-');
const joinDigits = groups => groups.map(group => group.join(''));
const extract = input => input.match(/\d/g);
const partition = n =>
a => Array.from(
{length: Math.floor((a.length - 1) / n) + 1},
(_, i) => a.slice(i * n, (i + 1) * n));
const partition3 = partition(3);
const data = "00 64 33 3-44-23 982- 23-1-0";
console.log(joinGroups(joinDigits(partition3(extract(data)))));

Categories

Resources