Javascript regex to match non repeating 9 digit number [duplicate] - javascript

I want to find 10 digit numbers with no repeat digits, for example:
1123456789 //fail, there are two 1's
6758951230 //fail, there are two 5's
6789012345 //pass, each digit occurs once only.
at the moment I am using regex but can only match 10digits numbers(it doesnt check for duplicates. I am using this regex:
[0-9]{10}
Can this be done with regex or is there a better way to achieve this?

This regex works:
^(?!.*(.).*\1)\d{10}$
This uses an anchored negative look ahead with a back reference to assert that there are no repeating characters.
See a live demo working with your examples.
In java:
if (str.matches("^(?!.*(.).*\\1)\\d{10}"))
// number passes

Try this one (?:([0-9])(?!.*\1)){10}, this will work if you're validating numbers one at a time.
This should work (?:([0-9])(?!\d*\1)){10} to search for each occurance of an unique 10-digit sequence, but it will fail with 12345678901234567890, will find the last valid part 1234567890 instead of ignoring it.
Source and explanations: https://stackoverflow.com/a/12870549/1366360

Here's the shortest and efficient regex with less backtracking due to the presence of a ?.
Works for any length of input:
!/(.).*?\1/.test(number)
Examples:
!/(.).*?\1/.test(1234567890) // true
!/(.).*?\1/.test(1234567490) // false - note that it also works for repeated chars which are not adjacent.
Demo
- checks for repeated digits
- opposite of what you want, because rubular doesn't allow a !

lancemanfv regex reference https://stackoverflow.com/a/12870549/1366360 is a great one, but the suggested regex is slightly off.
Instead try
^(?:([0-9])(?!.*\1)){10}$
This will match any string that begins and ends with 10 digits that are all different.
If you want to check (and extract) if a longer string contains a 10 digit number with each number different use this
((?:([0-9])(?!.*\2)){10})*
You can then use a numbered reference to extract the matching number

Works every time (I see this question) -
Revised to define Grp 10 before the (?! \10 ) assertion. \1-\9 are always considered backrefs (> \10, the parenth's must be before it is referenced).
So made them all the same as well.
Note- this can be used to find a floating (substring) 10 uinque digit number. Requires no anchors.
Fyi - With Perl, the \g{#} (or \k'name') syntax could be used before the group is defined, no matter what number the group number is.
# "(?:((?!\\1)1)|((?!\\2)2)|((?!\\3)3)|((?!\\4)4)|((?!\\5)5)|((?!\\6)6)|((?!\\7)7)|((?!\\8)8)|((?!\\9)9)|((?!\\10)0)){10}"
(?:
( # (1)
(?! \1 )
1
)
| ( # (2)
(?! \2 )
2
)
| ( # (3)
(?! \3 )
3
)
| ( # (4)
(?! \4 )
4
)
| ( # (5)
(?! \5 )
5
)
| ( # (6)
(?! \6 )
6
)
| ( # (7)
(?! \7 )
7
)
| ( # (8)
(?! \8 )
8
)
| ( # (9)
(?! \9 )
9
)
| ( # (10)
(?! \10 )
0
)
){10}

Related

Validate timestamp step by step with regex

This regular expression validates timestamps e.g. 2018-02-12 00:55:22:
[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1]) (2[0-3]|[01][0-9]):[0-5][0-9]:[0-5][0-9]
However, the timestamp should be validated step by step:
201 => true
201a => false
2018- => true
20189 => false
Is there a nice (short) regex extension?
......
Because your question has the javascript tag I am going to assume you are doing "step-by-step" validation like "onkeyup" or similar. The following pattern will validate your datetime string as it is being constructed (I'm including an empty string as valid so that no flag is triggered when empty; but you could change to \d{1,4} if you want to act on empty strings).
I am using \d whenever possible to reduce pattern length.
The x pattern modifier is in play with my dumped pattern, for easier reading. When you apply this to your project, you can compact it all and remove the x flag.
I am using non-capturing groups out of habit; since you are probably only matching, you can use capturing groups if you like.
Pattern Demo
Pattern:
~
^
(?:
\d{0,4}|
\d{4}-|
\d{4}-[01]|
\d{4}-(?:0[1-9]|1[0-2])|
\d{4}-(?:0[1-9]|1[0-2])-|
\d{4}-(?:0[1-9]|1[0-2])-[0-3]|
\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12]\d|3[0-1])|
\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12]\d|3[0-1])\s|
\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12]\d|3[0-1])\s[0-2]|
\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12]\d|3[0-1])\s(?:2[0-3]|[01]\d)|
\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12]\d|3[0-1])\s(?:2[0-3]|[01]\d):|
\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12]\d|3[0-1])\s(?:2[0-3]|[01]\d):[0-5]|
\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12]\d|3[0-1])\s(?:2[0-3]|[01]\d):[0-5]\d|
\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12]\d|3[0-1])\s(?:2[0-3]|[01]\d):[0-5]\d:|
\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12]\d|3[0-1])\s(?:2[0-3]|[01]\d):[0-5]\d:[0-5]|
\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12]\d|3[0-1])\s(?:2[0-3]|[01]\d):[0-5]\d:[0-5]\d
)
$
~
x
You can combine it to get 2 overall information blocks.
Incrementally match the form delimiters - - : :
while allowing/matching bad segments.
In the end you get info on the form progress.
And also the form segments.
You test the form's progress via capture groups 2,4,6,8,10
You test the date/time elements via groups 1,3,5,7,9,11
Though, you only need to test the elements up to the maximum group in the form
progress.
^(?:(?:([0-9]{4})|\d*)(-(?:(0[1-9]|1[0-2])|\d*)(-(?:(0[1-9]|[1-2][0-9]|3[0-1])|\d*)([ ]+(?:(2[0-3]|[01][0-9])|\d*)(:(?:([0-5][0-9])|\d*)(:(?:([0-5][0-9])|\d*))?)?)?)?)?)$
Formatted
^
(?:
(?:
( [0-9]{4} ) # (1)
| \d*
)
( # (2 start)
-
(?:
( 0 [1-9] | 1 [0-2] ) # (3)
| \d*
)
( # (4 start)
-
(?:
( 0 [1-9] | [1-2] [0-9] | 3 [0-1] ) # (5)
| \d*
)
( # (6 start)
[ ]+
(?:
( 2 [0-3] | [01] [0-9] ) # (7)
| \d*
)
( # (8 start)
:
(?:
( [0-5] [0-9] ) # (9)
| \d*
)
( # (10 start)
:
(?:
( [0-5] [0-9] ) # (11)
| \d*
)
)? # (10 end)
)? # (8 end)
)? # (6 end)
)? # (4 end)
)? # (2 end)
)
$
segments via if the capture groups matched.
Regex is not the way to do this.
Heres a simple function. You use a good date in the correct format, strip off the number of characters from the front that have been entered and combine it with the vale entered, then check if its valid
function validateDate($date)
{
$fakedate = "2018-02-12 00:55:22";
$date .= substr($fakedate, strlen($date));
$format = 'Y-m-d H:i:s';
$d = DateTime::createFromFormat($format, $date);
return $d && $d->format($format) == $date;
}
var_dump(validateDate('201')); bool(true)
var_dump(validateDate('201a')); bool(false)
var_dump(validateDate('2018-')); bool(true)
var_dump(validateDate('20189')); bool(false)

RegEx match rational literals with decimals except incomplete rational literals

To match numbers like -3+-1.5/45,32, I'm trying to write a Regular Expression, and I'm very close to what I need.
I have the following (JavaScript) regular expression to match decimal numbers in a certain format:
( // 1st alternative:
( [+-]? // an optional unary +-
[\d_]* // 0-9 and _ digit separator any number of times
[,.]? // one of these decimal separators, once
[\d]+ // 0-9 at least once
)
| // 2nd alternative
( [+-]? // an optional unary +-
[\d_]+ // 0-9 and _ digit separator, at least once
[,.]? // one of these decimal separators, once
[\d]* // 0-9 any number of times
)
)
That is, the previous matches 10_00_0000.90, 1_00,99, 0.9, 9, and .9 but not . or ,.
Next, I experimented with this regex to match rational number expressions using the regex mentioned above.
([+-]?[\d_]*[+-]?(([+-]?[\d_]*[,.]?[\d]+)|([+-]?[\d_]+[,.]?[\d]*))\/(([+-]?[\d_]*[,.]?[\d]*)|([+-]?[\d_]+[,.]?[\d]*)))
It works like:
(
[+-]? // optional unary +-
[\d_]* // optional 0-9 and _ digit separator (for compound numbers)
[+-]? // optional infix +- for 2+3/2 OR 2-2/3
( // begin the regex from above, for before the / numer / denom separator
( // all as above
[+-]? // this is intentional: the numerator itself may be signed
[\d_]*
[,.]?
[\d]+
)
|
(
[+-]?
[\d_]+
[,.]?
[\d]*
)
)
\/ // numerator / denominator separator
(([+-]?[\d_]*[,.]?[\d]*)|([+-]?[\d_]+[,.]?[\d]*))) // same as above
You can find the regex and a couple of tests here (click "unit tests" on the left, then click the play button): https://regex101.com/r/bB8eO2/5
So you don't have to click, here are my tests:
/5 assert that regex does not match PASS
4/5 assert that capture group 1 equals 4/5 PASS
-1/3 assert that capture group 1 equals -1/3 PASS
3/-8 assert that capture group 1 equals 3/-8 PASS
+4.12/-.90 assert that capture group 1 equals +4.12/-.90 PASS
+1-6/7. assert that capture group 1 equals +1-6/7. PASS
1-+6/7 assert that capture group 1 equals 1-+6/7 PASS
-1+-.4/5. assert capture group 1 equals -1+-.4/5. PASS
-1+-.4/ assert regex does not match FAIL
Everything works properly except that one last failing test. I've fiddled with the quantifiers in the denominator, and I can get the last test to pass, but then trailing decimal separators [.,] are left out and the second-to-last and first test fail: https://regex101.com/r/mQ9mN8/1
This is for a lexer, so it would be nice to use a regex and not yet a proper parser to just test: is this thing a number, or is it an identifier?
You can use
([+-]?[\d_]*[+-]?(?:[+-]?(?:[\d_]+(?:[,.]\d*)?|[.,]\d+))\/(?:[+-]?(?:[\d_]+(?:‌​[,.]\d*)?|[.,]\d+)))
See this regex demo
Pattern breakdown:
(
[+-]?[\d_]*[+-]? # Optional + or - followed with 0+ digits or underscore and again optional - or +
(?:[+-]? # optional - or +
(?:[\d_]+ # 1+ digits or underscore
(?:[,.]\d*)? # Optional sequence of a . or , followed with 0+ digits
| # or
[.,]\d+ # , or , followed with 1+ digits
)
)
\/
(?:[+-]? # optional - or +
(?:[\d_]+ # 1+ digits or underscore
(?:‌​[,.]\d*)? # Optional sequence of a . or , followed with 0+ digits
| # or
[.,]\d+ # , or , followed with 1+ digits
)
)
)

Regex to match any set of numbers except the 10 digit numbers starting with 7

I want to capture all numbers(any no.of digits) except the 10 digit numbers starting with 7.
71234567890 - should match
7123456789 - should not match
1234567890- should match
Use the pattern
/7\d{9}|(\d+)/
^^^^^^ MATCH 10-DIGIT NUMBER STARTING WITH SEVEN, DO NOT CAPTURE
^ --OR--
^^^^^ MATCH OTHER SEQUENCES OF DIGITS AND DO CAPTURE
This will match the 10-digit number starting with 7 but not capture it; otherwise, it will match the sequence of digits and capture it.
Now
'7123456789'.match(regexp)
["7123456789", undefined]
'1234567890'.match(regexp)
["1234567890", "1234567890"]
In other words, the captured string will be found in the second element of the array returned by match.
If you want to anchor this to the beginning and end of the string, then
/^7\d{9}$|(^\d+$)/
You could also do this with a negative look-ahead, as suggested in the comments, but it's not needed here and could be a bit of a stretch for beginning regexpers.
(?:(?:^|\D)(7\d{1,8}|7\d{10,})(?:\D|$))
See the DEMO
In order to get any number of digits except a string of 10 digits starting with '7'
you'd have to special case the '7'. There is really no way around it.
The fastest way is a pure regex solution, since the engine stays inside
running c++ engine code and does not interact with the host language.
There are two ways, either anchored or mid-string.
Anchored: ^(?:7(?!\d{9}$)|[012345689])\d*$
(number string is the overall match, i.e. in capture group 0)
^ # Beginning of string
(?: # Cluster, get first digit
7 # '7'
(?! \d{9} $) # not followed by nine more digits
| # or
[012345689] # Any digit except '7' (i.e. [^\D7])
) # End cluster
\d* # Get optional remaining digits
$
Mid-string: (?:^|\D)((?:7(?!\d{9}(?:\D|$))|[012345689])\d*)
(number string is in capture group 1)
(?: ^ | \D ) # Beginning of string or not a digit
( # (1 start), The number
(?: # Cluster, get first digit
7 # '7'
(?! # Assertion, not followed by nine more digits
\d{9}
(?: \D | $ ) # (forces no more/less than nine) digits
)
| # or
[012345689] # Any digit except '7' (i.e. [^\D7])
) # End cluster
\d* # Get optional remaining digits
) # (1 end)

trying to get a regex to match ranges

So far I have ^(\d.*[.]?\d*)|([<>][=]?\d.*[.]?\d*)|(\d.*[.]?\d*[-]\d.*[.]?\d*)$ but with my testing I get:
Should Match: (all do)
>1
<9
>=99
<=123123.134
1-2
44.421-234.123
123
123.123
0.123
Should not match: (examples marked with * are matching when they shouldn't)
123. *
.123
=<123 *
=>234 *
sdf
sdf.sdf
123.sdf *
Example here.
You can use something like this maybe:
^(?:[<>]?=?\d+(?:\.\d+)?|\d+(?:\.\d+)?-\d+(?:\.\d+)?)$
I trust that you already know how the anchors ^ and $ work.
(?: ... ) is a non-capture group, it's the same as a capture group ( ... ) except that it doesn't 'save' the matched parts. This is particular useful when you don't really need the matched part and you want to improve the efficiency, when compared to ( ... ) which takes a little overhead to store extra data.
[<>]?=? is for potential comparators.
\d+(?:\.\d+)? is used for numbers, integers or floating and ensure that there is no such thing as 123. or .123 since we are using the + quantifier on the \d.
So the regex matches a comparator followed by a number, or a subtraction between two numbers:
\d+(?:\.\d+)?-\d+(?:\.\d+)?
+-----------+|+-----------+
1st num | 2nd num
minus sign
regex101 demo
You can use this:
^(?:[<>]=?|\d+(?:.\d+)?-)?\d+(?:.\d+)?$

Javascript Regexp for all numeric and decimal point format

i'd like to make a javascript validation that will accept all numeric and decimal point format.
For example :
1,000,000.00 is OK
1.000.000,00 is OK
1.000,000.00 is not OK
1.000,000,00 is not OK
1,000.000,00 is not OK
1,000.000.00 is not OK
Based on what i got here is :
/^[1-9][0-9]{0,2}(,[0-9]{3})*(\.[0-9]{2})?$/ is only valid for 1,000,000.00 not for 1.000.000,00
How can i validate both format ?
Updated :
What if the thousand points are not compulsory such as :
1000000.00 is OK or
1000000,00 is OK
Assuming that the decimal part and thousands separators are mandatory, not optional, and that 0 is not an allowed value (as suggested by your examples and your regex):
^[1-9]\d{0,2}(?:(?:,\d{3})*\.\d{2}|(?:\.\d{3})*,\d{2})$
As a verbose regex:
^ # Start of string
[1-9]\d{0,2} # 1-3 digits, no leading zero
(?: # Match either...
(?:,\d{3})* # comma-separated triple digits
\.\d{2} # plus dot-separated decimals
| # or...
(?:\.\d{3})* # dot-separated triple digits
,\d{2} # plus comma-separated decimals
) # End of alternation
$ # End of string
Here is the regex that you want..
^(([1-9]\d{0,2}(((\.\d{3})*(,\d{2})?)|((,\d{3})*(\.\d{2})?)))|(0(\.|,)\d{1,2})|([1-9]\d+((\.|,)\d{1,2})?))$
This is the link that proves that it can handles all cases
http://regexr.com?2tves
The best way to look at a regular expression this big is to blow it up to
a very large font and split it on the alternatives (|)
var s='1,000,000.00';// tests
var result= /(^\d+([,.]\d+)?$)/.test(s) || // no thousand separator
/((^\d{1,3}(,\d{3})+(\.\d+)?)$)/.test(s) || // comma thousand separator
/((^\d{1,3}(\.\d{3})+(,\d+)?)$)/.test(s); // dot thousand separator
alert(result)
Put together its a brute-
function validDelimNum2(s){
var rx=/(^\d+([,.]\d+)?$)|((^\d{1,3}(,\d{3})+(\.\d+)?)$)|((^\d{1,3}(\.\d{3})+(,\d+)?)$)/;
return rx.test(s);
}
//tests
var N= [
'10000000',
'1,000,000.00',
'1.000.000,00',
'1000000.00',
'1000000,00',
'1.00.00',
'1,00,00',
'1.000,00',
'1000,000.00'
]
var A= [];
for(var i= 0, L= N.length; i<L; i++){
A.push(N[i]+'='+validDelimNum2(N[i]));
}
A.join('\n')
/* returned values
10000000=true
1,000,000.00=true
1.000.000,00=true
1000000.00=true
1000000,00=true
1.00.00=false
1,00,00=false
1.000,00=true
1000,000.00=false
*/
The simplest (though not most elegant by far) method would be to write analogous RE for another case and join them with 'OR', like this:
/^(([1-9][0-9]{0,2}(,[0-9]{3})*(\.[0-9]{2})?)|([1-9][0-9]{0,2}(\.[0-9]{3})*(,[0-9]{2})?))$/
UPDATE
A little cleaned up version
/^[1-9]\d{0,2}(((,\d{3})*(\.\d{2})?)|((\.\d{3})*(,\d{2})?))$/
You can replace the , and \. with [,.] to accept either in either location. It would also make 1,000.000.00 OK though.
Its harder to make the regexp behave like that in JavaScript because you can't use lookbehinds
/^(0|0[.,]\d{2}|[1-9]\d{0,2}((,(\d{3}))*(\.\d{2})?|(\.(\d{3}))*(,\d{2})?))$/
/^ #anchor to the first char of string
( #start group
0 # 0
| # or
0[.,] # 0 or 0 followed by a . or ,
\d{2} # 2 digits
| # or
[1-9] #match 1-9
\d{0,2} #0-2 additional digits
( #start group
(,(\d{3}))* # match , and 3 digits zero or more times
(\.\d{2})? # match . and 2 digits zero or one
| # or
(\.(\d{3})* # match . and 3 digits zero or more times
(,\d{2})? # match , and 2 digits zero or one time
) #end group
) #end group
$/ #anchor to end of string
http://jsfiddle.net/AC3Bm/

Categories