regex allows one character (it should not) why? - javascript

Hello I am trying to create a regex that recognizes money and numbers being inputted. I have to allow numbers because I am expecting non-formatted numbers to be inputted programmatically and then I will format them myself. For some reason my regex is allowing a one letter character as a possible input.
[\$]?[0-9,]*\.[0-9][0-9]
I understand that my regex accepts the case where multiple commas are added and also needs two digit after the decimal point. I have had an idea of how to fix that already. I have narrowed it down to possibly the *\. as the problem
EDIT
I found the regex expression that worked [\$]?([0-9,])*[\.][0-9]{2} but I still don't know how or why it was failing in the first place
I am using the .formatCurrency() to format the input into a money format. It can be found here but it still allows me to use alpha characters so i have to further masked it using the $(this).inputmask('Regex', { regex: "[\$]?([0-9,])*[\.][0-9]{2}" }); where input mask is found here and $(this) is a reference to a input element of type text. My code would look something like this
<input type="text" id="123" data-Money="true">
//in the script
.find("input").each(function () {
if ($(this).attr("data-Money") == "true") {
$(this).inputmask('Regex', { regex: "[\$]?([0-9,])*[\.][0-9]{2}" });
$(this).on("blur", function () {
$(this).formatCurrency();
});
I hope this helps. I try creating a JSfiddle but Idk how to add external libraries/plugin/extension

The "regular expression" you're using in your example script isn't a RegExp:
$(this).inputmask('Regex', { regex: "[\$]?([0-9,])*[\.][0-9]{2}" });
Rather, it's a String which contains a pattern which at some point is being converted into a true RegExp by your library using something along the lines of
var RE=!(value instanceof RegExp) ? new RegExp(value) : value;
Within Strings a backslash \ is used to represent special characters, like \n to represent a new-line. Adding a backslash to the beginning of a period, i.e. \., does nothing as there is no need to "escape" the period.
Thus, the RegExp being created from your String isn't seeing the backslash at all.
Instead of providing a String as your regular expression, use JavaScript's literal regular expression delimiters.
So rather than:
$(this).inputmask('Regex', { regex: "[\$]?([0-9,])*[\.][0-9]{2}" });
use
$(this).inputmask('Regex', { regex: /[\$]?([0-9,])*[\.][0-9]{2}/ });
And I believe your "regular expression" will perform as you expect.
(Note the use of forward slashes / to delimit your pattern, which JavaScript will use to provide a true RegExp.)

Firstly, you can replace '[0-9]' with '\d'. So we can rewrite your first regex a little more cleanly as
\$?[\d,]*\.\d\d
Breaking this down:
\$? - A literal dollar sign, zero or one
[\d,]* - Either a digit or a comma, zero or more
\. - A literal dot, required
\d - A digit, required
\d - A digit, required
From this, we can see that the minimum legal string is \.\d\d, three characters long. The regex you gave will never validate against any one character string.
Looking at your second regex,
[\$]? - A literal dollar sign, zero or one
([0-9,])* - Either a digit or a comma, subexpression for later use, zero or more
[\.] - A literal dot, required
[0-9]{2} - A digit, twice required
This has the exact same minimum matchable string as above - \.\d\d.
edit: As mentioned, depending on the language you may need to escape forward slashes to ensure they aren't misinterpretted by the language when processing the string.
Also, as an aside, the below regex is probably closer to what you need.
[A-Z]{3} ?(\d{0,3}(?:([,. ])\d{3}(?:\2\d{3})*)?)(?!\2)[,.](\d\d)\b
Explanation:
[A-Z]{3} - Three letters; for an ISO currency code
? - A space, zero or more; for readability
( - Capture block; to catch the integer currency amount
\d{0,3} - A digit, between one and three; for the first digit block
(?: - Non capturing block (NC)
([,. ]) - A comma, dot or space; as a thousands delimiter
\d{3} - A digit, three; the first possible whole thousands
(?: - Non capturing block (NC)
\2 - Match 2; the captured thousands delimiter above
\d{3} - A digits, three
)* - The above group, zero or more, i.e. as many thousands as we want
)? - The above (NC) group, zero or one, ie. all whole thousands
) - The above group, i.e everything before the decimal
[.,] - A comma or dot, as a decimal delimiter
(\d{2}) - Capture, A digit, two; ie. the decimal portion
\b - A word boundry; to ensure that we don't catch another
digit in the wrong place.
The negative lookahead was provided by an answer from John Kugelman in this question.
This correctly matches (matches enclosed in square brackets):
[AUD 1.00]
[USD 1,300,000.00]
[YEN 200 000.00]
I need [USD 1,000,000.00], all in non-sequential bills.
But not:
GBP 1.000
YEN 200,000

Related

Javascript regex to make sure that string matches format x:y

I am trying to parse a string which has two numbers, both can be between 1 and 3 digits, and will have a colon in between. Here are some examples:
"1:1"
"1:12"
"12:1"
"123:12"
Also, the given string may also be invalid, and I need to detect if it is. My attempts so far to make sure the string is valid have looked like this: .match(/[1-9]\:[1-9]/);. But then I noticed that this wont work if a string such as this is inputted: "characters12:4characters". How would I go about validating the string to make sure it is in the format x:y?
Any help would be deeply appreciated.
Edit: numbers which contain 0 at the beginning is valid, but may not be given.
You may use
/^\d{1,3}:\d{1,3}$/
See the regex demo
Details
^ - start of a string
\d{1,3} - one, two or three digits (\d is a shorthand character class that matches any digit (it can also be written as a [0-9] character class) and {1,3} is a limited quantifier that matches1 to 3 consecutive occurrences of the quantified subpattern)
: - a colon
\d{1,3} - one, two or three digits
$ - end of the string.

Javascript regex "replace(/[ -_]/g)" deletes numbers?

I was doing some tests in Javascript with the replace javascript function.
Consider the following examples executed on a node REPL.
It's a replace that deletes spaces, hyphens and underscores from a string.
> "call this 9344 5 66 22".replace(/[ _-]/g, '');
'callthis934456622'
That was what I was expecting. To only delete the spaces.
However take a look at this:
> "call this 9344 5 66 22".replace(/[ -_]/g, '');
'callthis'
Why when I put this regex combination exact like this -_ (space, hyphen, underscore) it deletes the numbers in the string?
More tests I did:
-(space, hyphen) does not deletes numbers
_(space, underscore) does not deletes numbers
_-(space, underscore, hyphen) does not deletes numbers
-_(hyphen, underscore, space) does not deletes numbers
_-(underscore, hyphen, space) REPL blocks??
-_(space, hyphen, underscore) does deletes numbers
[ -_] means characters from space (ASCII 32) to _ (ASCII 95) which includes, among other things, numbers and capital letters.
What you are looking for is [ \-_]. Escaping the - will make it act like the character instead of the meta-character for ranges.
Hyphen if not present at start or end position in a character class needs to be escaped otherwise it represents a range.
So this regex:
[ -_]
will match anything from space to underscore i.e. ASCII 32-95
The - character has special meaning in character classes. When it appears between two characters, it represents a character range — e.g. [a-z] matches any character with a character code between a and z, inclusive.
However, as you've observed, when it's placed at the beginning or end of the character class, it just represents a literal - character. This can also be accomplished by escaping the - within the character class — i.e. [ \-_].
"call this 9344 5 66 22".replace(/(\s|-|_)/g, '');
In a class, the dash - character has special meaning as a range operator ONLY when
it doesn't separate clauses, parsed left to right.
Otherwise it is considered no different than any other literal.
Regular expression parsers have no time to worry about good form.
So you can put the dash anywhere you want as a literal, as long as it separates clauses (i.e. its not ambigous).
Most people put it at the end or beginning or escape it so no conceptual errors occur.
Example of clauses, which are hilighted, and literal dashes:
[-a-z-\p{L}-0-9-\x00-\x09-\x20-]

JavaScript RegEx Matches Invalid Number

I am getting inconsistent results when using JavaScript's RegEx to validate numbers with a decimal place. The goal is to have any combination of digits followed by a decimal point and two more digits. It works fine except with numbers in the thousands (no separators).
This is the expression I'm using:
^[0-9]+(\.[0-9][0-9])$
Valid numbers:
10.99
0.75
999.99
5000.99
...etc
Invalid Numbers:
1000
.75
0
...etc
The problem is that it matches whole numbers in the thousands. This is for an internal application so I'm not concerned about using additional separators. I've tested the expression out with tools like http://regexpal.com/ which gives me the results that I need, so it appears that there is something in the JS causing the issue.
You can duplicate the problem here:
http://jsfiddle.net/hcAcQ/
You need to escape the backslash before the ., I believe:
^[0-9]+(\\.[0-9][0-9])$
The reason that a 4 digit (or greater) number will work is because the single backslash isn't actually escaping that . to be a period character, thus causing it to act as the wildcard "match any character" dot.
When you have 3 or fewer digits this fails because there aren't enough characters for every match in the regex, but the with 4 digits it will work (one digit for the first character class, one for the ., and one each for the other two character classes.
Escaping the \ will cause the . to actually be interpreted as a literal . character, as you probably intended. You could also instead define your variable as a regex literal (MDN example; near the top) so that you don't have to deal with escaping \ characters within the string:
//instead of new valueFormat = new RegExp('^[0-9]+(\\.[0-9])$');
valueFormat = /^[0-9]+\.[0-9][0-9]$/;
This works(\. instead of .):
// valueFormat = new RegExp('^([0-9]+)(\.[0-9][0-9])$');
valueFormat = new RegExp('^([0-9]+)(\\.[0-9][0-9])$');

JavaScript RegExp to match a (partial) hour

I want to allow people to enter times into a textbox in various formats. One of the formats would be either:
2h for 2 hours, or
2.5h for 2 and a half hours
I want to use a regex to recognise the pattern but it's not picking it up for some reason:
I have:
var hourRegex = /^\d{1,2}[\.\d+]?[h|H]$/;
which works for 2h, but not for 2.5h.
I thought that this regex would mean - Start at the beginning of the string, have one or two digits, then have none or one decimal points which if present must be followed by one or more digits then have a h or a H and then it must be the end of the string.
I have tried the regex tool here but no luck.
/^\d{1,2}(?:\.\d+)?h$/i; Use parentheses instead of square braces.
Start at the beginning
One or two digits
Optional: a dot followed by at least one digit
End with a h
Case insensitive
RegExp tuturial
[...] - square braces mean: anything which is within the provided range.
[^...] means: Match a character which is not within the provided range
(...) - parentheses mean: Group me. Optionally, the first characters of a group can start with:
?: - Don't reference me (me, I = group)
?= - Don't include me in the match, though I have to be here
?! - I may not show up at this point
{a,b}, {a,} means: At least a, maximum b characters. Omitting b = Infinity
+ means: at least one time, match as much as possible equivalen to {1,}
* means: match as much as possible equivalent to {0,}
+? and *? have the same effect as previously described, with one difference: Match as less as possible
Examples
[a-z] One character, any character between a, b, c, ..., z
(a-z) Match "a-z", and group it
[^0-9] Match any non-number character
See also
MDN: Regular Expressions - A more detailed guide
The trouble is here :
[\.\d+]
you can not use character classes inside brackets.
Use this instead:
(\.[0-9]+)?
You've confused your square brackets with your parenthesis. Square brackets look for a single match of any contained character, whereas parenthesis look for a match of the entire enclosed pattern.
Your issue lies in [\.\d+]? It's looking for . or 0-9 or +.
Instead you should try:
/^\d{1,2}(\.\d+)?(h|H)$/
Although that will still allow users to enter invalid numbers, such as 99.3 which is probably not the expected behavior.

Regular expression to match numbers, finite ranges, and infinite ranges (such as >=9)

What can be a regular expression for following type of string
E.g. 1, 2-3, 4..5, <6, <=7, >8, >=9
Here I am using equals, range (-), sequence (..) & greater than/equal to operators for numbers less than 100. These numbers are separated by a comma.
Pls help me in writing a regular expression for this. Thanks in advance.
Atul
How about something like this:
^(\d+(-|\.\.)|[<>]=?)?\d+$
Example using Python:
>>> import re
>>> pattern = '^(\d+(-|\.\.)|[<>]=?)?\d+$'
>>> for s in '1, 2-3, 4..5, <6, <=7, >8, >=9'.split(','):
... print(re.match(pattern, s.strip()).group(0))
...
1
2-3
4..5
<6
<=7
>8
>=9
To be clear, this regex matches only one element in the list. I highly recommend that you preprocess your input by splitting it on commas and trimming the individual elements, like I did in the example above. Even though that's not strictly necessary (you can add this logic to the regex I gave here), it will but quite a bit more efficient and readable.
How the regex works:
Observe that every valid string ends with one or more digits, thus \d+$.
There may or may not be something before that, thus, ^(...)?\d+$.
Those prefixes are either the start of a range, or a comparison:
\d+(-|\.\.) matches a number followed by a dash or two periods.
<=? matches "<" as well as "<=". Likewise for >=?. We can abbreviate this to [<>]=?.
Combining these two options using a pipe (|), which signifies choice, we get
^(\d+(-|\.\.)|[<>]=?)?\d+$
Try this expression:
^(?:\d+(?:(?:\.\.|-)\d+)?|[<>]=?\d+)(?:,\s*\d+(?:(?:\.\.|-)\d+)?|[<>]=?\d+)*$
It consists of the alternation of
\d+(?:(?:\.\.|-)\d+)? for a number followed by an optional expression for a range or sequence, and
[<>]=?\d+ for the inequalities.
That’s repeated in the second parts with a comma and optional whitespace for the list.
And for the condition of only allowing numbers less than 100, you can replace \d+ with [1-9]\d for 1..99 or (?:0|[1-9]\d) for 0..99.
You should totally use a regular expression tool like regex buddy.
You're trying to verify that your string generally looks like the sample?
1, 2-3, 4..5, <6, <=7, >8, >=9
matches
\s*(\d+|\d+-\d+|\d+\.\.\d+|[<>]=?\d+)\s*(,\s*(\d+|\d+-\d+|\d+\.\.\d+|[<>]=?\d+)\s*)*
It's easier to split on , and then match each part with
\s*(\d+|\d+-\d+|\d+\.\.\d+|[<>]=?\d+)\s*
That reads:
white space trimmed, match digits or digits dash digits, or digits dot dot digits, or one of less-than or greater-than with optional equal to digits.
You can compress that down to the harder to read:
\s*((\d+(-|\.\.)|[<>]=?)?\d+)\s*
If you want all your digits to be 1-2 digits only, then change all the \d+ to \d{1,2} or \d\d?

Categories

Resources