Regular Expressions have always seemed like black magic to me and I have never been able to get my head around building them.
I am now in need of a Reg Exp (for validation putsposes) that checks that the user enters a number according to the following rules.
no alpha characters
can have decimal
can have commas for the thousands, but the commas must be correctly placed
Some examples of VALID values:
1.23
100
1,234
1234
1,234.56
0.56
1,234,567.89
INVALID values:
1.ab
1,2345.67
0,123.45
1.24,687
You can try the following expression
^([1-9]\d{0,2}(,\d{3})+|[1-9]\d*|0)(\.\d+)?$
Explanation:
The part before the point consists of
either 1-3 digits followed by (one or more) comma plus three digits
or just digits (at least one)
If then follows a dot also some digits must follow.
^(((([1-9][0-9]{0,2})(,[0-9]{3})*)|([0-9]+)))?(\.[0-9]+)?$
This works for all of your examples of valid data, and will also accept decimals that start with a decimal point. (I.e. .61, .07, etc.)
I noticed that all of your examples of valid decimals (1.23, 1,234.56, and 1,234,567.89) had exactly two digits after the decimal point. I'm not sure if this is coincidence, or if you actually require exactly two digits after the decimal point. (I.e. maybe you're working with money values.) The regular expression as I've written it works for any number of digits after the decimal point. (I.e. 1.2345 and 1,234.56789 would be considered valid.) If you need there to be exactly two digits after the decimal point, change the end of the regular expression from +)?$ to {2})?$.
try to use this regex
^(\d{1,3}[,](\d{3}[,])*\d{3}(\.\d{1,3})?|\d{1,3}(\.\d+)?)$
I know you asked for a regex but I think it's much saner to just call double.TryParse() and consider your input acceptable if that method returns true.
double dummy;
var isValid=double.TryParse(text, out dummy);
It won't match your testcases exactly; the major difference being that it is very lenient with commas (so it will accept two of your INVALID inputs).
I'm not sure why you care, but if you really do want comma strictness you could do a preprocessing step where you only check the validity of comma placement and then call double.TryParse() only if the string passes the comma placement test. (If you want to be truly careful, you'll have to honor the CultureInfo so you can know what character is used for separators, and how many digits there are between separators, in the environment your program finds itself in)
Either approach results in code that is more "obviously right" than a regex. For example, you won't have to live with the fear that your regex left out some important case, like scientific notation.
Related
I am trying to compose a regular expression to match a numeric value expressed as a decimal multiple of .25 (ex. 1.25, 14.75).
// Must Match
1.0
1.25
1.250000
1.5
1.500
1.75
1.7500
// Must Not Match
1.2
1.46
1.501
1.99
So far I have the following expression: \d+(\.((0+)|(250*)|(50*)|(750*))). It works when I use online tooling like gskinner.com/regexr. When I use the expression in a validation attribute to seed my EntityFramework db, it produces validation errors:
[RegularExpression(#"^\d+(\.((0+)|(250*)|(50*)|(750*)))$", ErrorMessage = "Hours must be 15 minute increments expressed as decimals (ex. .0, .25, .5, .75)")]
public double Hours { get; set; }
Similar question (I am looking for a way to round the decimal portion of numbers up or down to the nearest .25, .5, .75, or whole number) but I need to use a regular expression to use the above data annotation.
Question:
Anyone see what's wrong with my expression?
Bonus points if you can extend it to support whole numbers (ex. 4 or 4.25 but not 4. or 4.62)
To match such number use regex pattern
(?!0\d)\d+(?:[.](?:25|5|75|0)0*)?(?!\d)
To validate input to be such number use regex pattern
^(?!0\d)\d+(?:[.](?:25|5|75|0)0*)?$
In both cases, the very first part (?!0\d) is optional to disallow match/validate numbers with invalid leading zeros, such as 000003.250, when match would trim them and take just 3.250; validation would fail if this optional part is present in the regex.
This matches whole numbers too:
^\d+(\.(25|5|75|0)0*)?$
I tested it with RegexHero. It has a .NET Regex engine in the backstage. If you're using all test cases together, make sure that you make Multiline option selected, so that ^ and $ symbols match each line individually, not the whole text.
I have a list of post codes which should be excluded from my shipping methods.
Suppose I have to exclude Scilly Isles, Isle of Man and few others.
For the above 2 areas valid post codes are IM1-IM9, IM86, IM87, IM89. And if it is IM25 or IM85 it is invalid.
I have writtent following expression. But it is returning even it is IM25 or IM 85.
var regex = new Regex("(PO3[0-9]|PO4[0-1]|GY[1-9]|JE[1-5]|IM[1-9]|TR[1-9])");
If I am passing IM85, to my expression it should return false. for IM1-IM9,, IM86, IM87, IM89 it should return true.
Same with TR post codes also. TR1-TR27 is a valid post code. If I give TR28, it should return false.
I am using '|' to seperate multiple patterns. Is that the right way of including multiple patterns in 1 expression.
What do you expect? What should be matched and what not? And please give an example of the string you want to test.
If you match your pattern against "IM25" it will match because you do allow IM[1-9] in your pattern, so you get a valid partial match. If you want to avoid that (I am not sure what you want to achieve) and want to allow really only a single digit after the first letters, use a "word boundary" \b and specify exactly what you want to allow, something like this:
(PO3[0-9]|PO4[0-1]|GY[1-9]|JE[1-5]|IM([1-9]|8[6-9])|TR([1-9]|2[0-7]))\b
See it here on Regexr
this would allow for the "IM" part also 6-9 as a second digit when there is a 8 before.
Update
It is still not clear what the context of your task is. I assume you have a list of valid Postcodes, probably it would be better, you extract the post code or only the first part of it (for that you can eventually use a regex) and check if it is in the list or not.
The actual validation is on the wikipedia site... Google has the answers ;) http://en.wikipedia.org/wiki/Postcodes_in_the_United_Kingdom#Validation
(GIR 0AA)|(((A[BL]|B[ABDFHLNRSTX]?|C[ABFHMORTVW]|D[ADEGHLNTY]|E[HNX]?|F[KY]|G[LUY]?|H[ADGPRSUX]|I[GMPV]|JE|K[ATWY]|L[ADELNSU]?|M[EKL]?|N[EGNPRW]?|O[LX]|P[AEHLOR]|R[GHM]|S[AEGKLMNOPRSTY]?|T[ADFNQRSW]|UB|W[ADFNRSV]|YO|ZE)[1-9]?[0-9]|((E|N|NW|SE|SW|W)1|EC[1-4]|WC[12])[A-HJKMNPR-Y]|(SW|W)([2-9]|[1-9][0-9])|EC[1-9][0-9]) [0-9][ABD-HJLNP-UW-Z]{2})
I still think you need more clarification. As a huge Regex guy, I would like to point out that multi-digit ranges should try to be put into the code side, not the Regex side, just for your sanity. But I personally like to play with Regex in this way. Regex reads one character at a time, so it only recognizes zero through nine. Not ten, not twenty eight. If you want to allow the following:
28 through 347
Then it becomes pretty complicated.
To put it into words, you want to allow:
If Two Digits, allow 2-9 for the first digit, and:
If the first digit is a Two, then allow 8/9 for the second digit,
ElseIf the first Digit is 3-9, then allow 0-9 for the second digit
Elseif Three Digits, allow 1-3 for the first Digit, and:
If the first digit is a Three, then allow 0-4 for the second digit, and:
If the second digit is a Four, then allow 0-7 for the third digit,
ElseIf the second digit is 0-3, then allow 0-9 for the third digit.
ElseIf the first digit is 1/2, then allow 0-9 for both the Second and Third digits.
Then with that, you can write a proper Regex like so, which searches for a word boundary or non-Digit surrounding a 2-pair or 3-pair. With this type of Problem-Solving, you should be able to figure out your Regex issue. Otherwise, let us know more about EXACTLY What you want to Match and NOT Match:
(\b|\D)((2[89]|[3-9][0-9])(\b|\D)|(3(4[0-7]|[0-3][0-9])|[12][0-9][0-9])(\b|\D))
I have changed my approach.
Instead of going for a regular expression which is becoming more complex, I am saving all the excluded outward codes of UK post codes.
And if any post code contains the particular outward code, excluding the post code from the list.
Outward codes are in this format
XX-YYY
XXX-YYY
XXXX-YYY
In all above formats, X represents outward code of an UK postcode.
I'm, quite frankly, completely clueless about Regular expression, more so building them. I am reading in a string that could contain any sort of combination of characters and numbers. What I know for certain is, somewhere in the string, there will be a number followed by % (1%, 13% etc.), and I want to extract that number from the string.
Examples are;
[05:37:25] Completed 21% //want to extract 21
[05:32:34] Completed 18000000 out of 50000000 steps (36%). //want to extract 36
I'm guessing I should be using either regex.Replace or regex.Split, but beyond that, I'm not sure. Any help would be appreciated.
You should be able to use something like "(\d+)%". This will match any number of consecutive digit characters, then a percent sign, and will capture the actual number so you can extract and parse it. Use this in Regex.Match(), and browse the Matches array of the result (I think it'll be the second element in the array, index 1).
If you need a decimal point, use "(\d+(\.\d+)?)%", which will match a string of digits, followed by a decimal point, then another set of digits.
The regex you want is:
/(\d+)%/
This will capture any number of digits immediately preceding a percentage sign.
([\d]+)(%)
The parentheses will group the result.
The [\d]+ gives you any digit, repeated one or more times.
The "%" is just a literal.
You will need to make sure you extract only the first grouping. Also, you will need to be sure that there are no other instances of "<number>%" in the line.
I'm not entirely sure how to make this C# specific, but I'm sure you can figure that out. :-P
Most likely you will need to use double-backslashes (\\) where I only had one.
What would be the following regular expressions for the following strings?
56AAA71064D6
56AAA7105A25
Would the regular expression change if the numbers rolled over? What I mean by this is that the above numbers happen to contain hexadecimal values and I don't know how the value changes one it reaches F. Using the first one as an example: 56AAA71064D6, if this went up to
56AAA71064F6 and then the following one would become 56AAA7106406, this would create a different regular expression because where a letter was allowed, now their is a digit, so does this make the regular expression even more difficult. Suggestions?
A manufacturer is going to enter a range of serial numbers. The problems are that different manufacturers have different formats for serial numbers (some are just numbers, some are alpha numeric, some contain extra characters like dashes, some contain hexadacimal values which makes it more difficult because I don't know how the roll over to the next serial number). The roll over issue is the biggest problem because the serial numbers are entered as a range like 5A1B - 6F12 and without knowing how the roll over, it seems to me that storing them in the database is not as easy. I was going to have the option of giving the user the option to input the pattern (expression) and storing that in the databse, but if a character or characters changes from a digit to a letter or vice versa, then the regular expression is no longer valid for certain serial numbers.
Also, the above example I gave is with just one case. There are multitude of serial numbers that would contain different expressions.
There's no single regular expression which is "the" expression to match both of those strings. Instead, there are infinitely many which will do so. Here are two options at opposite ends of the spectrum:
(56AAA71064D6)|(56AAA7105A25)
.*
The first will only match those two strings. The second will match anything. Both satisfy all the criteria you've given.
Now, if you specify more criteria, then we'd be able to give a more reasonable idea of the regular expression to provide - and that will drive the answers to the other questions. (At the moment, the only answer that makes sense is "It depends on what regex you use.")
I think you could do it this way for 12 characters. This will search for a 12 character phrase where each of the characters must be a capital (A or B or C or D or E or F or 1 or 2 or 3 or 4 or 5 or 6 or 7 or 8 or 9 or 0)
[A-F0-9]{12}
If you're wanting to include the possibility of dashes then do this.
[A-F0-9\-]{12}
Or you're wanting to include the possibility of dashes plus the 12 characters then do this. But that would pick up any 12-15 character item that fit the criteria though.
[A-F0-9\-]{12,15}
Or if it's surrounded by spaces (AAAAHHHh...SO is stripping out my spaces!!!)
[A-F0-9\-]{12}
Or if it's surrounded by tabs
\t[A-F0-9\-]{12}\t
This match a string that contains 12 hexa
[0-9A-F]{12}
Assuming these are all 12-digit hexadecimal numbers, which it looks like they are, the following regex should work:
[0-9A-Fa-f]{12}
Here I'm using a character class to say that I want any digit, OR A-F, OR a-f. As a bonus I'm allowing lowercase letters; if you don't want those just get them out of the regex.
As Jon Skeet and others have said, you really didn't provide enough information, so if you don't like this answer please understand that I was doing the best I can with what information you provided.
So, how about this:
[0-9A-F]{12}
Well it sounds like you're describing a 12 digit hexadecimal number:
^[A-F0-9]{12}$
Is there an easy way to take a dynamic decimal value and create a validation regular expression that can handle this?
For example, I know that /1[0-9]{1}[0-9]{1}/ should match anything from 100-199, so what would be the best way to programmatically create a similar structure given any decimal number?
I was thinking that I could just loop through each digit and build one from there, but I have no idea how I would go about that.
Ranges are difficult to handle correctly with regular expressions. REs are a tool for text-based analysis or pattern matching, not semantic analysis. The best that you can probably do safely is to recognize a string that is a number with a certain number of digits. You can build REs for the maximum or minimum number of digits for a range using a base 10 logarithm. For example, the match a number between a and b where b > a, construct the RE by:
re = "[1-9][0-9]{"
re += str(log10(a)-1)
re += "-"
re += str(log10(b)-1)
re += "}"
Note: the example is in no particular programming language. Sorry, C# not really spoken here.
There are some boundary point issues, but the basic idea is to construct an RE like [1-9][0-9]{1} for anything between 100 and 999 and then if the string matches the expression, convert to an integer and do the range analysis in value space instead of lexical space.
With all of that said... I would go with Mehrdad's solution and use something provided by the language like decimal.TryParse and then range check the result.
^[-]?\d+(.\d+)?$
will validate a number with an optional decimal point and / or minus sign at the front
No, is the simple answer. Generating the regex that will work correctly would be more complicated than doing the following:
Decimal regex (find the decimal numbers in a string). "^\$?[+-]?[\d,]*(\.\d*)?$"
Convert result to decimal and compare to your range. (decimal.TryParse)
This depends on where and what you want to parse.
Using the bellow RegEx to parse strings for numbers.
Can handle comma's and dots.
[^\d.,](?<number>(\d{1,3}(\.\d{3})*,\d+|\d{1,3}(,\d{3})*\.\d+|\d*[,\.]\d+|\d+))[^\d.,]