Confusing with Regular Expressions repeaing parts - javascript

I am really confused with Regular Expressions repeating parts with curly braces. Consider the following example:
var dateTime = /\d{1,2}\/\d{1,2}\/\d{4} \d{1,2}:\d{2}/;
console.log(dateTime.test("30/1/2003 8:45"));
// true
Now if I change 30 to 300000 and 45 to 455555, I'll get true again! Other parts between outer numbers are ok and the result is as expected.
Can somebody help me find the problem?
Thanks.

You're not matching the beginning and end of the String (^ and $) so it's just finding a match anywhere in the String which still happens, and then giving true.
300000/1/2003 8:455555
dd/m/yyyy h:mm
You probably want
/^\d{1,2}\/\d{1,2}\/\d{4} \d{1,2}:\d{2}$/;
Or to be even more exact;
/^(?:0?[1-9]|[12]\d|3[01])\/(?:0?[1-9]|1[0-2])\/\d{4} (?:0?\d|1\d|2[0-3]):[0-5]\d$/;
(?:pattern) non capture group
pattern? the n in pattern is optional
[1-9] character class; a number ranging from 1 to 9
pattern1|pattern2 either pattern1 or pattern2
[12] character class; either 1 or 2
\d same as [0-9]
pattern{4} the n in pattern happens 4 times

You're not matching the whole string, just part of it - using the test function, that's enough to return True.
Try this instead:
/^\d{1,2}\/\d{1,2}\/\d{4} \d{1,2}:\d{2}$/
The ^ anchor matches the beginning of the string, the $ one matches the end of the string.

You can find more useful information about a match by using string.match(regex) rather than regex.test(string).
In this case, you'd see that it's matching 00/1/2003 8:45 because you did not use ^ and $ to mark the start and end of the subject string, respectively.

What is happening is that when you change 30 to 30000, the last two zeroes(00) of 30000 are matched and with 45555 the matching is stopped with first two digits(45) and the rest of the string is not matched.
To stop that from happening, you have to indicate that the string must begin and end with regex specified.
This can be done using anchors. Like this -
var dateTime = /^\d{1,2}\/\d{1,2}\/\d{4} \d{1,2}:\d{2}$/;
^ ^

Related

Regex for digits and hyphen only

I am trying to understand regex, for digits of length 10 I can simply do
/^[0-9]{10}$/
for hyphen only I can do
/^[-]$/
combining the two using group expression will result in
/^([0-9]{10})|([-])$/
This expression does not work as intended, it somehow will match part of the string instead of not match at all if the string is invalid.
How do I make the regex expression that accepts only "-" or 10 digits?
It would have worked fine to combine your two regexps exactly as you had them. In other words, just use the alternation/pipe operator to combine
/^[0-9]{10}$/
and
/^[-]$/
as is, directly into
/^[0-9]{10}$|^[-]$/
↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑ YOUR ORIGINAL REGEXPS, COMBINED AS IS WITH |
This can be represented as
and that would have worked fine. As others have pointed out, you don't need to specify the hyphen in a character class, so
/^[0-9]{10}$|^-$/
↑ SIMPLIFY [-] TO JUST -
Now, we notice that each of the two alternatives has a ^ at the beginning and a $ at the end. That is a bit duplicative, and it also makes it little harder to see immediately that the regexp is always matching things from beginning to end. Therefore, we can rewrite this, as explained in other answers, by taking the ^ and $ out of both sub-regexps, and combine their contents using the grouping operator ():
/^([0-9]{10}|-)$/
↑↑↑↑↑↑↑↑↑↑↑↑↑ GROUP REGEXP CONTENTS WITH PARENS, WITH ANCHORS OUTSIDE
The corresponding visualization is
That would also work fine, but you could use \d instead of [0-9], so the final, simplest version is:
/^(\d{10}|-)$/
↑↑ USE \d FOR DIGITS
and this visualizes as
If for some reason you don't want to "capture" the group, use (?:, as in
/^(?:\d{10}|-)$/
↑↑ DON'T CAPTURE THE GROUP
and the visualization now shows that group is not captured:
By the way, in your original attempt to combine the two regexps, I noticed that you parenthesized them as in
/^([0-9]{10})|([-])$/
↑↑↑↑↑↑↑↑↑↑↑ ↑↑↑↑↑ YOU PARENTHESIZED THE SUB-REGEXPS
But actually this is not necessary, because the pipe (alternation, of "or") operator has low precedence already (actually it has the lowest precedence of any regexp operator); "low precedence" means it will apply only after things on both side are already processed, so what you wrote here is identical to
/^[0-9]{10}|[-]$/
which, however, still won't work for the reasons mentioned in other answers, as is clear from its visualization:
How do I make the regex expression that accepts only "-" or 10 digits?
You can use:
/^([0-9]{10}|-)$/
RegEx Demo
Your regex is just asserting presence of hyphen in the end due to misplacements of parentheses.
Here is the effective breakdown of OP's regex:
^([0-9]{10}) # matches 10 digits at start
| # OR
([-])$ # matches hyphen at end
which will cause OP's regex to match any input starting with 10 digits or ending with hyphen making these invalid inputs also a valid match:
1234567890111
1234----
------------------
1234567890--------
To get the regex expression that accepts only "-" or 10 digits - change your regexp as shown below:
^(\d{10}|-)$
DEMO link
The problem with your regex is it's looking for strings either
starting with 10 digits i.e. ^([0-9]{10}) or
ends with "-" - i.e. ([-])$
You needs an addtional wrapping ^( .. )$ to get this work. i.e.
/^(([0-9]{10})|([-]))$/
Better yet /^([0-9]{10}|-)$/ since [-] and - are both the same.

Regexp: numbers and few special characters

I am buried in a RegExp hell and can't find way out, please help me.
I need RegExp that matches only numbers (at least 1 number) and one of this characters: <, >, = (exactly one of them one time).
My reg. expression looks like this:
^[0-9]+$|^[=<>]{1}$
And I thought it should match when my string containts one or more digits and exactly 1 special character defined by me. But it doesn't act correctly. I think there might be problem with my start/end of string definition but Im not sure about that.
Examples that should pass include:
<1
=2
22>
>1
=00123456789
Examples that should not pass this reg. exp.:
<<2
==222
<>=2
I thought it should match when my string containts one or more digits and exactly 1 special character
No, the original pattern matches a string contains one or more digits or exactly 1 special character. For example it will match 123 and = but not 123=.
Try this pattern:
^\d+[=<>]$
This will match that consists of one or more digits, followed by exactly one special character. For example, this will match 123= but not 123 or =.
If you want your special character to appear before the number, use a pattern like this instead:
^[=<>]\d+$
This will match =123 but not 123 or =.
Update
Given the examples you provided, it looks like you want to match any string which contains one or more digits and exactly one special character either at the beginning or the end. In that case use this pattern:
^([=<>]\d+|\d+[=<>])$
This will match <1, =2, 22>, and >1, but not 123 or =.
Just use [0-9]+[=<>]
Here are visualizers of your regexp and this one:
http://www.regexper.com/#%5E%5B0-9%5D%2B%24%7C%5E%5B%3D%3C%3E%5D%7B1%7D%24
http://www.regexper.com/#%5B0-9%5D%2B%5B%3D%3C%3E%5D
Your regex says:
1 or more numbers OR 1 symbol
Also, the ^ and $ means the whole string, not contains. if you want a contains, drop them. I don't know if you have a space between the number and symbol, so put in a conditional space:
[0-9]+\s?[=<>]{1}
This should work.
^[0-9]+[=<>]$
1 or more digits followed by "=<>".
Try this regex:
^\d+[=<>]$
Description
This one:
/^\d+[<>=]$|^[<>=]\d+$/

jQuery/JavaScript regex to match any three first characters followed by an exact string

I need a regular expression to validate a form, based on the value of a drop down. The value, however, is randomly generated by PHP (but is always a 2 digit number).
It needs to be valid for "38|One Evening" The number 38 is what's going to change. So far, I have
//return value of dropdown
var priceOption = $("#price_option-4").val();
//make sure it ends with "One Evening"
var oneEvening = priceOption.match(/^ * + 'One Evening' $/);
Which I thought would match any string as long as it's followed by "one evening"
strings are not to be use with regex, you should just write what you want to match\test inside the regex literal, without the quotes.
/^\d{2}\|One Evening$/.test(priceOption);
// ^^^^^^ Begins with two digits
// ^^ Escaped the | meta char.
// ^^^^^^^^^^^^ Then until the end: One Evening
Simply use
/^\d\d\|One Evening$/.test(priceOption);
For xx|One Evening
/^\d{2}\|One Evening$/
/^.+?One Evening$/
Breaking it down
// ^ starts with
// . any character
// + quantifier - one or more of preceding character
// ? non-greedy - ensure regex stops at One Evening.
// One Evening = literal text
// $ match end of string.
Note that my answer reflects the requirement to match any sequence of characters, then One Evening.
I think you may be better off being more specific and ensuring you definitely have two numeric characters.
If you can it is best to be specific. Try the following:
// <start of string> <2 digits> <|One Evening> <end of string>
/^\d{2}\|One Evening$/.test( priceOption );

JavaScript and regular expressions: get the number of parenthesized subpattern

I have to get the number of parenthesized substring matches in a regular expression:
var reg=/([A-Z]+?)(?:[a-z]*)(?:\([1-3]|[7-9]\))*([1-9]+)/g,
nbr=0;
//Some code
alert(nbr); //2
In the above example, the total is 2: only the first and the last couple of parentheses will create grouping matches.
How to know this number for any regular expressions?
My first idea was to check the value of RegExp.$1 to RegExp.$9, but even if there are no corresponding parenthseses, these values are not null, but empty string...
I've also seen the RegExp.lastMatch property, but this one represents only the value of the last matched characters, not the corresponding number.
So, I've tried to build another regular expression to scan any RegExp and count this number, but it's quite difficult...
Do you have a better solution to do that?
Thanks in advance!
Javascripts RegExp.match() method returns an Array of matches. You might just want to check the length of that result array.
var mystr = "Hello 42 world. This 11 is a string 105 with some 2 numbers 55";
var res = mystr.match(/\d+/g);
console.log( res.length );
Well, judging from the code snippet we can assume that the input pattern is always a valid regular expression, because otherwise it would fail before the some code partm right? That makes the task much easier!
Because We just need to count how many starting capturing parentheses there are!
var reg = /([A-Z]+?)(?:[a-z]*)(?:\([1-3]|[7-9]\))*([1-9]+)/g;
var nbr = (' '+reg.source).match(/[^\\](\\\\)*(?=\([^?])/g);
nbr = nbr ? nbr.length : 0;
alert(nbr); // 2
And here is a breakdown:
[^\\] Make sure we don't start the match with an escaping slash.
(\\\\)* And we can have any number of escaped slash before the starting parenthes.
(?= Look ahead. More on this later.
\( The starting parenthes we are looking for.
[^?] Make sure it is not followed by a question mark - which means it is capturing.
) End of look ahead
Why match with look ahead? To check that the parenthes is not an escaped entity, we need to capture what goes before it. No big deal here. We know JS doens't have look behind.
Problem is, if there are two starting parentheses sticking together, then once we capture the first parenthes the second parenthes would have nothing to back it up - its back has already been captured!
So to make sure a parenthes can be the starting base of the next one, we need to exclude it from the match.
And the space added to the source? It is there to be the back of the first character, in case it is a starting parenthes.

Regular Expression for date validation - Explain

I was surfing online for date validation, but didn't exactly understand the regex. Can anyone explain it? I'm confused with ?, {} and $. Why do we need them?
dateReg = /^[0,1]?\d{1}\/(([0-2]?\d{1})|([3][0,1]{1}))\/(([1]{1}[9]{1}[9]{1}\d{1})|([2-9]{1}\d{3}))$/;
? means “zero or one occurences”.
{x} (where x is a number) means “exactly x occurences”
$ means “end of line”
These are very basic regex, I recommand you to read some documentation.
^ = beginning of the string
[0,1]? = optional zero, one or comma (the comma is probably an error)
\d{1} = exactly one digit (the {1} is redundant)
\/ = a forward slash
[0-2]? = optional zero, one or two (range character class) followed by any single digit (\d{1})
OR [3] = three (character class redundant here) followed by exactly one zero, one or comma
\/ = forward slash
[1]{1}[9]{1}[9]{1}\d{1} = 199 followed by any digit
OR 2-9 followed by any 3 digits
Overall, that's a really poorly written expression. I'd suggest finding a better one, or using a real date parser.
In Javascript you could validate date by passing it to Date.Parse() function. Successful conversion to a date object means you have a valid date.
Wouldn't recommend using regex for this. Too many edge cases and code gets hard to maintain.
? means "Zero or one of the aforementioned"
{n} means "exactly n of the aforementioned"
$ is the end of the String (Thanks #Andy E)
To summarize briefly:
`?' will match 0 or 1 times the pattern group you put in front of it. In this case, it's possibly being misused and should be left out, but it all depends on just what you want to match.
`{x}' tells the regex to match the preceding pattern group exactly x times.
`$' means to match the end of the line.
Well:
^ // start of the text
$ // end of the text
X{n} // number n inside these curly parenthesis define how many exact occurrences of X
X{m,n} // between m to n occurrences of X
X? // 0 or 1 occurrence of X
\d // any digits 0-9
For more help about Javascript date validation please see: Regular Expression to only grab date

Categories

Resources