Regex that does not allow zeros - regex

I use this regex:
/^(?!0000)(?!0+(?:[.,]\d{1,2})?$)\d{1,4}(?:[.,]\d{1,2})?$/
It allows decimal numbers (. and , separators), with two digits after the separator. It does not allow zero values. What I want to do is to make it allow numbers like 0.1 and 0.09 etc... Here it's impossible to write any number starting with 0. I don't know how to do this. Any idea?
Thanks.

You can simplify your regex with just one negative lookahead:
/^(?![,.0]*$)\d{1,4}(?:[.,]\d{1,2})?$/gm
RegEx Demo
(?![,.0]*$) will prevent any input with just 0s, dots or commas in input.

Any regex based approach would be trivial to bypass. For example, they could use any of the following to evade your regex filter:
+0- Start with +
-0 - Start with -
0e0 - Scientific notation
1e-999 - Not real 0, but most likely will be one after conversion.
And any combination of methods above.
Long story short: regex wouldn't work here.
Try to cast your string to a number and reject if it equals to 0.
You should be able to do that in most languages, including JavaScript.

Since you mentioned JS/Angular, you may replace all , with . (in case the decimal separator is ,) and cast the string to a number to check if it is zero, and if it is, then use your simplified regex /^\d{1,4}(?:[.,]\d{1,2})?$/ that makes sure there are 1 to 4 digits in the whole part and 1 to 2 digits in the fractional part:
function check(str) {
str = str.replace(/,/g, ".");
if ( parseFloat(str) > 0 ) {
return /^\d{1,4}(?:\.\d{1,2})?$/.test(str);
}
return false;
}
console.log(check("0,00"));
console.log(check("0,09"));
console.log(check("900000"));
If you cannot access the code, adjust the negative lookahead like
^(?!0+(?:[.,]0+)?$)\d{1,4}(?:[.,]\d{1,2})?$
See the regex demo
The (?!0+(?:[.,]0+)?$) negative lookahead fails the match only if the string starts with 1 or more zeros, and then has an optional sequence of , or . followed with 1 or more zeros.
^ - start of a string
(?!0+(?:[.,]0+)?$) - reject the match if it matches a sequence of
0+ - 1 or more zeros
(?:[.,]0+)? - an optional sequence of . or , followed with 1 or more zeros
\d{1,4} - 1 to 4 digits
(?:[.,]\d{1,2})? - an optional sequence of:
[.,] - a . or ,
\d{1,2} - any 1 or 2 digits
$ - end of string.
The lookahead pattern may be reduced to (?!0*[.,]?0+$), since the consuming pattern will ensure the correct format is matched.

Related

Regex expression for numbers and leading zeros just with a dot and decimal

I'm trying to find a regex for numeric inputs. We can receive a leading 0 just if we add a dot for adding 1 or 2 decimal numbers. And of course just accept numbers.
These are the scenarios that we can accept:
0.01
1.1
1.02
120.01
We can't accept these values
0023
0100
.01
.12
Which regex is the best option for these cases?
Until now we try we the following regex for accepting just number and dots
[A-Za-z,]
And also we try with the following ones:
^[+-]?[0-9]{1,3}(?:[0-9]*(?:[.,][0-9]{1})?|(?:,[0-9]{3})*(?:\.[0-9]{1,2})?|(?:\.[0-9]{3})*(?:,[0-9]{1,2})?)$
"/^[-]?[$]\d{1,3}(?:,?\d{3})*\.\d{2}$/"
"/(^(\d{1})\.{0,1}([0-9]){0,2}$)|(^([1-9])\d{0,2}(\,\d{0,3})$)/g"
(?:0|[1-9][0-9]*)(?:\.[0-9]{1,2})?
And the next one for deleting the leading zeros but it didn't work for 0.10 cases
^0+
If a negative lookahead is supported, you can exclude matches that start with a zero and have no decimal part.
^(?!0\d*$)\d+(?:\.\d{1,2})?$
^ Start of string
(?!0+\d*$) Negative lookahead, assert not a zero followed by optional digits at the right
\d+ Match 1+ digits
(?:\.\d{1,2})? Match an optional decimal part with 1 or 2 digits
$ End of string
Regex demo
I would go with ^(0|[1-9]\d*|(0|[1-9]\d*)\.\d+)$
You can test here: https://regex101.com/r/oNMgR9/1
Explanation
^ means : match the beginning of the string (or line if the m flag is enabled).
$ means : match the end of the string (or line if the m flag is enabled).
(a|b) means match "a" or match "b" so I'll use this to match either "0" alone or any number not starting with a "0". It's the syntax for a logical or.
. alone is used to match any char. So you have to escape it if you want to match the dot character. This is why I wrote 0\. instead of 0..
[ ] is used to list some characters you want to match. It can be a range if you use the - char, so [1-9] means any digit char from "1" to "9".
\d is to match a digit. It's totally equivalent to [0-9].
* means : match the preceding pattern 0 or many times, so \d* means that it will match 0 or many times a digit, so it will match "8" or "465" or "09" but also an empty string "". If you want to match the preceding pattern at least once or many times then you use + instead of *. So \d+ won't match an empty string "" but \d* would match it.
A) Just a number not starting with 0
[1-9]\d* will match any digit from 1 to 9 and then optionnaly followed by other digits. This will match numbers without a decimal point.
B) Just 0
0 alone is a possibility. This is because the case above isn't covering it.
B) A number with decimals
(0|[1-9]\d*)\.\d+ will match either a "0" alone or a number not starting by "0" and then followed by a point and some other digits (which have to be present because we don't want to match "45." without the numbers behind the dot).
Better alternative
The solution from #TheFourthBird is a bit cleaner with the use of a negative lookahead. It's just a bit different to understand. And he read the question completely: You wanted 1 or 2 digits after the decimal. I forgot about that, so, effectively, \d+ should be replaced by \d{1,2} as you don't want more than 2 digits.
You can use
^(?![0.]+$)(?:[1-9]\d*|0)(?:\.\d{1,2})?$
See the regex demo.
Details:
^ - start of string
(?![0.]+$) - fail the match if there are just zeros or dots till end of string
(?:[1-9]\d*|0) - either a non-zero digit followed with any zero or more digits or a zero
(?:\.\d{1,2})? - optionally followed with a sequence of a . and one or two digits
$ - end of string.

A RegEx that matches correct comma placement in a string

I am wanting to check user input to where it check whether a string has correct comma placement, and if the number is valid in human eyes too.
These are numbers that are allowed:
1,000
100
1
1,000,000,000,000,000
Here are numbers that are not allowed:
1e+5
1e5
1,00
-105
100.50
100,00,00,0,000000
I've tried to come up with my own RegEx but this is very complicated for even me to understand. This is my RegEx (^[0-9]{0,3}(,[0-9]*)?$) but it is very broken at the moment.
Is anyone able to help?
You may use
^\d{1,3}(?:,\d{3})*$
See the regex demo
Details
^ - start of string
\d{1,3} - 1, 2 or 3 digits
(?:,\d{3})* - zero or more consecutive occurrences of
, - a comma
\d{3} - 3 digits
$ - end of string.

Regex compare whole number and ignore separators

I would like to match the following pattern
1.XXXXXX.XXX.X
The combination must begin with a 1 and must contain at least a second number greater than 0 somewhere. Only numbers and points allowed.
So the following examples would be correct
1.000000.000.1
1.000500.000.0
1.020030.030.0
And the following examples would be incorrect
1.000000.000.0
1.0000.00.0
1.0000d0.020.0
What I have created so far
(?=^[1][\.][0-9]{6}[\.][0-9]{3}[\.][0-9]{1}$) // check pattern 1.XXXXXX.XXX.X
(?=^[1-9](?!0000000000$)[0-9][1-9]?\d+$) // check if input is greater than 10000000000
Unfortunately, the second statement does not work because of the points in the input. Is it possible to read the complete number and ignore the points or is there a better solution?
You may use
^1\.(?!(?:\.?0)+$)\d{6}\.\d{3}\.\d$
See the regex demo
The regex will fail the match if there are only zeros and dots after the initial 1..
Details
^1\. - 1. at the start of the string
(?!(?:\.?0)+$) - a negative lookahead that will fail the match of there are one or more sequences of an optional . and a zero up to the end of the string
\d{6} - 6 digits
\. - a dot
\d{3} - 3 digits
\. - a dot
\d - a digit
$ - end of string.

Regex range between 0 and 100 including two decimal

I'm trying to figure out a regex expression that does the following. Both conditions below must be true:
1) Between 0 and 100 inclusive
2) Can contain one or two decimals only but not obligatory.
It should not allow 100.01 or 100.1
100 is the maximum value, or 100.0 or 100.00
I tried ^(100(?:\.00)?|0(?:\.\d\d)?|\d?\d(?:\.\d\d)?)$
which helped me in this question
but this does not accept 99.0 (one decimal).
I'm probably very close.
You just need to make each second decimal digit optional:
^(?:100(?:\.00?)?|\d?\d(?:\.\d\d?)?)$
^ ^
See the updated regex demo. The 0(?:\.\d\d)? alternative is covered by \d?\d(?:\.\d\d)? one (as per Sebastian's comment) and can thus be removed.
The ? quantifier matches one or zero occurrences of the subpattern it quantifies.
Pattern details:
^ - start of string
(?: - start of an alternation group:
100(?:\.00?)? - 100, 100.0 or 100.00 (the .00 is optional and the last 0 is optional, too)
\d?\d(?:\.\d\d?)? - an optional digit followed by an obligatory digit followed with an optional sequence of a dot, a digit and an optional digit.
) - end of the alternation group
$ - end of string.
BONUS: If the number can have either . (dot) or , (comma) as a decimal separator, you can replace all \. patterns in the regex with [.,]:
^(?:100(?:[.,]00?)?|\d?\d(?:[.,]\d\d?)?)$

Regex for allowing numbers without leading and ending 0

I want except some numbers in different syntax and I am trying to find the best Regex for this task/match.
First some valid numbers:
0.01
0.2
0.38
45
165.6
52732.08
999999999.99
And here some invalid numbers:
.01
.2
.50
.85
45.
45.0
45.00
00045.0
124.60
000124.60
124,6
000053853.01
999.999.999,99
999999999,99
After several tests I have created the following Regex:
^[1-9]?\d{1,9}\.?\d{1,2}(?<!0)$
But I always struggling on the number: 000058723.01
Any ideas? Thanks.
You can use this regex:
^(?!0+\d)\d+(?:\.(?![1-9]*0+$)\d{1,2})?$
Or:
^(?:0+|[1-9]\d*)(?:\.(?![1-9]*0+$)\d{1,2})?$
RegEx Demo
Try this pattern:
^((?:0|[1-9]+)(?:\.(?:\d+?[1-9]|[1-9]))?)$
Demo
You accept four kinds of input:
A number with no decimal places and without leading zeroes: [1-9]\d*
Zero followed by a dot followed by digits (without trailing zeroes): 0\.\d*[1-9]
A decimal number without leading or trailing zeroes: [1-9]\d*\.\d*[1-9]
Zero: 0
Putting the four together:
^([1-9]\d*|0\.\d*[1-9]|[1-9]\d*\.\d*[1-9]|0)$
Here is a fixed version of your regex:
^(?!0{2,})\d+(?:\.\d{1,2}(?<!0))?$
Here, initial 2 or more zeros are not allowed with the lookahead (?!0{2,}), and the decimal part is made optional within a non-capturing group (?:\.\d{1,2}(?<!0))?.
See demo
In case you do not want to match 0, you can exclude this in the negative lookahead:
^(?!0{2,}|0$)\d+(?:\.\d{1,2}(?<!0))?$
^^
See Demo 2
A number with optional decimals is composed from two pieces: the integer part and the optional decimal part that starts with a dot.
The integer part is either zero (0) or a sequence of digits that start with 1..9 (no 0) and can continue with zero or more digits:
0|[1-9][0-9]*
If you need to impose an upper limit on the integer part's length then replace * with {,n} where n is the maximum allowed length minus 1.
The decimal part starts with a dot (.) followed by zero or more digits and followed by one of 1..9 (no 0 allowed at the end).
The expression is:
\.[0-9]*[1-9]
Now let's combine them:
^(0|[1-9][0-9]*)(\.[0-9]*[1-9])?$
What I added when I joined the pieces:
^ - match the start of the string; without this the regex matches 45.0 from 00045.0;
parentheses around the integer part because of the lower precedence of |;
parentheses around the decimal part, followed by ? to signal the entire decimal part is optional;
$ - match the end of the string to avoid matching 124.6 from 124.60.
Remarks
The above regex was designed to match your examples. However, please notice that most programming languages allow most or all of the numbers you put in the "invalid" section and use a dot (.) as decimal separator. And many languages provide library functions that are able to parse the numbers that use a comma (,) as decimal separator.
Numbers without integer part (.85), without digits after the dot (45.) ore with trailing zeros (45.0) are valid and are interpreted without ambiguity.
The only troublemaker is the leading zero (00045.0). For integer numbers, most of the times it is a signal that the number is represented in base 8 while for real numbers it is simply ignored.