Javascript Regular Expressions - accept non-zero for first number in amount - javascript

I want to accept a number that does not start with zero but later values can be zero.
I am using var.replace(/[^1-9]/g, ''); which do not let me to enter 0 at all.
valid:
10
9990
invalid:
01
0999
i should not be able to enter 0 at first place. If 0 is entered it should get replace with '' blank that is the logic

If you want to check if the first value value isn't zero, you can simply do a substr:
Inputvalue.substr(0,1) !== '0'
If you want all leading zeroes replaced:
Inputvalue.replace(/^0+/, '');
The ^ means 'string begins with', then 'one or more' (+) zeroes.
If you want all leading zeroes before a digit(\d) replaced:
Inputvalue.replace(/^0+\d/, '');
The ^ means 'string begins with', then 'one or more' (+) zeroes.
If you want to get the first digit after the zeroes:
The ^ character means 'start of string'. You say it could be 000001, the 1 is not at the start of the string, so that will never match.
I find it helpful to define what I want in text:
I want the first digit, only one -> [1-9]
Starts with (^) with one or more (+) zeroes -> ^0+
That results in ^0+[1-9].
We only want to store the digit, so we place that in a group: ^0+([1-9])
const examples = [
'123', // no starting zeroes
'0123', // match
'000123', // match
'132000123', // no matching zeroes, dont match the end either!
];
console.log(examples.map(function (example) {
const matches = example.match(/^0+([1-9])/);
return example + ' -> ' + (matches !== null ? matches[1] : 'no match!');
}));

You can use a negative lookahead to be sure that the 1rst digit is not zero:
var test = [
'0123',
'000001',
'abc',
'123',
'102030',
];
console.log(test.map(function (a) {
return a + ' :' + /^(?!0)\d+$/.test(a);
}));

The escape \d matches any digit from 0-9.
Since you said that the number must not start with zero, we can start by writing [1-9].
So, the final regex will look like: /^[1-9]\d*$/g.
This will match any non-zero positive number, provided that's the entire string.
You can auto-validate form inputs with this regex.
<input pattern='^[1-9]\d*$'>

Related

Struggling with RegEx validation and formating for specfici ID format

I have couple specific string formatting i want to achieve for different entities:
Entity 1: 1111-abcd-1111 or 1111-abcd-111111
Entity 2: [10 any symbol or letter(all cap) or number]-[3 letters]
Entity 3: [3 letters all cap]-[3 any]-[5 number]
Not sure if Regex is best approach, because i also want to use this as validator when user starts typing the char's it will check against that Entity selected and then against it's RegEx
Here is a regex with some input strings:
const strings = [
'1111-abcd-1111', // match
'1111-abcd-111111', // match
'1111-abcd-1111111', // no match
'ABCS#!%!3!-ABC', // match
'ABCS#!%!3!-ABCD', // nomatch
'ABC-#A3-12345', // match
'ABC-#A3-1234' // no match
];
const re = /^([0-9]{4}-[a-z]{4}-[0-9]{4,6}|.{10}-[A-Za-z]{3}|[A-Z]{3}-.{3}-[0-9]{5})$/;
strings.forEach(str => {
console.log(str + ' => ' + re.test(str));
});
Result:
1111-abcd-1111 => true
1111-abcd-111111 => true
1111-abcd-1111111 => false
ABCS#!%!3!-ABC => true
ABCS#!%!3!-ABCD => false
ABC-#A3-12345 => true
ABC-#A3-1234 => false
Explanation of regex:
^ - anchor text at beginning, e.g. what follows must be at the beginning of the string
( - group start
[0-9]{4}-[a-z]{4}-[0-9]{4,6} - 4 digits, -, 4 lowercase letters, -, 4-6 digits
| - logical OR
.{10}-[A-Za-z]{3} - any 10 chars, -, 3 letters
| - logical OR
[A-Z]{3}-.{3}-[0-9]{5} - 3 uppercase letters, -, any 3 chars, -, 5 digits
) - group end
$ - anchor at end of string
Your definition is not clear; you can tweak the regex as needed.

Use Regex for phone number

I'm working on a Regex.
let phones = ['321-1234567','+355 321 1234567','0103 1234500', '00 355 3211234567' ]
I want to have the following results:
3211234567
+3553211234567
+3551031234500
+3553211234567
I have implemented this:
phones.forEach(phone => {
phone = phone.replace(/^0+/,'+355').replace(/[^+\d]+/g, '')
console.log(phone)
})
Output:
3211234567
+3553211234567
+3551031234500
+3553553211234567 --->wrong , it should be: +3553211234567
and it works only for the three first elements of array, but it doesn't work for the last one (the case when we should replace those two zeros with + ).
So, when the phone number starts with a zero, replace that first zero with +355, when it starts with 00, replace those two zeros with + .
How can I do that using a Regex, or should I use conditions like if phone.startsWith()?
My question is not a duplication of: Format a phone number (get rid of empty spaces and replace the first digit if it's 0)
as the solution there doesn't take in consideration the case when the phone number starts with 00 355 .
let phones = ['321-1234567','+355 321 1234567','0103 1234500', '00 355 3211234567' ]
phones = phones.map(r => r
.replace(/^00/,'+')
.replace(/^0/,'+355')
.replace(/[^+\d]+/g, '')
)
console.log(phones)
You can use
let phones = ['321-1234567','+355 321 1234567','0103 1234500', '00 355 3211234567' ]
for (const phone of phones) {
console.log(
phone.replace(/^0{1,2}/, (x) => x=='00'?'+':'+355')
.replace(/(?!^\+)\D/g, ''))
}
Details:
.replace(/^0{1,2}/, (x) => x=='00'?'+':'+355') - matches 00 or 0 at the start of string, and if the match is 00, replacement is +, else, replacement is +355 (here, x stands for the whole match value and if ? then : else is a ternary operator)
.replace(/(?!^\+)\D/g, '') removes any non-digit if it is not + at the start of string.
Regex details:
^0{1,2} - ^ matches start of string and 0{1,2} matches one or two zero chars
(?!^\+)\D - (?!^\+) is a negative lookahead that fails the match if the char immediately to the right is + that is located at the start of the string (due to ^ anchor), and \D matches any char other than a digit.
your only problem is in this line replace(/^0+/,'+355') replace this with replace(/^0+/,'+')
phones.forEach(phone => {
phone = phone.replace(/^0+/,'+').replace(/[^+\d]+/g, '')
console.log(phone)
})

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);

Javascript replace regex to accept only numbers, including negative ones, two decimals, replace 0s in the beginning, except if number is 0

The question became a bit long, but it explains the expected behaviour.
let regex = undefined;
const format = (string) => string.replace(regex, '');
format('0')
//0
format('00')
//0
format('02')
//2
format('-03')
//-3
format('023.2323')
//23.23
format('00023.2.3.2.3')
//23.23
In the above example you can see the expected results in comments.
To summarize. I'm looking for a regex not for test, for replace which formats a string:
removes 0s from the beginning if it's followed by any numbers
allows decimal digits, but just 2
allows negative numbers
allows decimal points, but just one (followed by min 1, max 2 decimal digits)
The last one is a bit difficult to handle as the user can't enter period at the same time, I'll have two formatter functions, one will be the input in the input field, and one for the closest valid value at the moment (for example '2.' will show '2.' in the input field, but the handler will receive the value '2').
If not big favour, I'd like to see explanation of the solution, why it works, and what's the purpose of which part.
Right now I'm having string.replace(/[^\d]+(\.\[^\d{1,2}])+|^0+(?!$)/g, ''), but it doesn't fulfill all the requirements.
You may use this code:
const arr = ['0', '00', '02', '-03', '023.2323', '00023.2.3.2.3', '-23.2.3.2.3']
var narr = []
// to remove leading zeroes
const re1 = /^([+-]?)0+?(?=\d)/
// to remove multiple decimals
const re2 = /^([+-]?\d*\.\d+)\.(\d+).*/
arr.forEach( el => {
el = el.replace(re1, '$1').replace(re2, '$1$2')
if (el.indexOf('.') >= 0)
el = Number(el).toFixed(2)
narr.push(el)
})
console.log(narr)
//=> ["0", "0", "2", "-3", "23.23", "23.23"]
If you aren't bound to the String#replace method, you can try this regex:
/^([+-])?0*(?=\d+$|\d+\.)(\d+)(?:\.(\d{1,2}))?$/
Inspect on regex101.com
It collects the parts of the number into capturing groups, as follows:
Sign: the sign of the number, +, - or undefined
Integer: the integer part of the number, without leading zeros
Decimal: the decimal part of the number, undefined if absent
This regex won't match if more then 2 decimal places present. To strip it instead, use this:
/^([+-])?0*(?=\d+$|\d+\.)(\d+)(?:\.(\d{1,2})\d*)?$/
Inspect on regex101.com
To format a number using one of the above, you can use something like:
let regex = /^([+-])?0*(?=\d+$|\d+\.)(\d+)(?:\.(\d{1,2}))?$/
const format = string => {
try{
const [, sign, integer, decimal = ''] = string.match(regex)
return `${(sign !== '-' ? '' : '-')}${integer}${(decimal && `.${decimal}`)}`
}catch(e){
//Invalid format, do something
return
}
}
console.log(format('0'))
//0
console.log(format('00'))
//0
console.log(format('02'))
//2
console.log(format('-03'))
//-3
console.log(format('023.23'))
//23.23
console.log(format('023.2323'))
//undefined (invalid format)
console.log(format('00023.2.3.2.3'))
//undefined (invalid format)
//Using the 2nd regex
regex = /^([+-])?0*(?=\d+$|\d+\.)(\d+)(?:\.(\d{1,2})\d*)?$/
console.log(format('0'))
//0
console.log(format('00'))
//0
console.log(format('02'))
//2
console.log(format('-03'))
//-3
console.log(format('023.23'))
//23.23
console.log(format('023.2323'))
//23.23
console.log(format('00023.2.3.2.3'))
//undefined (invalid format)
Another option is to use pattern with 3 capturing groups. In the replacement, use all 3 groups "$1$2$3"
If the string after the replacement is empty, return a single zero.
If the string is not empty, concat group 1, group 2 and group 3 where for group 3, remove all the dots except for the first one to keep it for the decimal and take the first 3 characters (which is the dot and 2 digits)
^([-+]?)0*([1-9]\d*)((?:\.\d+)*)|0+$
In parts
^ Start of string
( Capture group 1
[-+]? Match an optional + or -
) Close group
0* Match 0+ times a zero
( Capture group 2
[1-9]\d* Match a digit 1-9 followed by optional digits 0-9
) Close group
( Capture group 3
(?:\.\d+)* Repeat 0+ times matching a dot and a digit
) Close group
| Or
0+ Match 1+ times a zero
$ End of string
Regex demo
const strings = ['0', '00', '02', '-03', '023.2323', '00023.2.3.2.3', '-23.2.3.2.3', '00001234', '+0000100005.0001']
let pattern = /^([-+]?)0*([1-9]\d*)((?:\.\d+)*)|0+$/;
let format = s => {
s = s.replace(pattern, "$1$2$3");
return s === "" ? '0' : s.replace(pattern, (_, g1, g2, g3) =>
g1 + g2 + g3.replace(/(?!^)\./g, '').substring(0, 3)
);
};
strings.forEach(s => console.log(format(s)));

Regular expression to accept both positive and negative numbers

I need a regular expression that helps me to accept both positive and negative numbers
I have used ^-?\d*(.\d+)?$ expression
validateNegativeNumber(e: any) {
let input = String.fromCharCode(e.charCode);
const reg = /^-?\d*(.\d+)?$/;
if (!reg.test(input)) {
e.preventDefault();
}
}
Expected result: 5, +5, -5, 0
Unexpected results: 1.5, -1.5, 5++++, ++5, ---5, 5--, 50--6
You missed checking for + sign. Also there is no need for capturing groups.
Use this:
^[+-]?\d+$
An optional + or - sign at the beginning
Followed by one or more digits till the end
Demo
You can use the pattern attribute of input tag in HTML, like below:
<input pattern="^[+-]?\d+$">
Explanation: pattern attribute is available, it is better use rather than calling a function that validates the input. That will be an extra work.
I hope it helps.
Use this, for accept positive or negative both number.
^-?[0-9]\d*(\.\d+)?$
^[+-]?\d+(?:\.\d+)?$
Explanation:
^ matches the beginning of the string (so "abc212" will not validate)
[+-]? the first allowed char che be + o - matching 0 or 1 occurrence (the ?). Note that if you don't want the + sign, you can just write -?, so the regex will validate matching 0 or 1 occurrence of - as first char
\d+ after that you can have any number of digits (at least one, because we user the +)
(?:\.\d+)? at the end we can have 0 or 1 occurrence (given by the ?) of a dot (\.) followed by any number of digits (\d+). Note that the ?: at the beginning of the group says that this is a "non-capturing group")
$ matches the ending of the string (so "231aaa" will not validate)
How about this one?
const reg = /^[+-]?\d*(\.\d+)?$/;
const valids = ['+5', '-5', '5', '-5', '-0.6', '.55', '555.124'];
const invalids = ['--5', '5+', '5-'];
console.log('testing for valids array');
valids.forEach(valid => {
console.log(reg.test(valid));
});
console.log('testing for invalids array');
invalids.forEach(invalid => {
console.log(reg.test(invalid));
});

Categories

Resources