I need a regular expression to check that a string's value is either a '0', or a positive number with a length equal to 1 to 10 (also where the first digit cannot be zero).
I'm stuck, I can get the 0, but I can't get the positive number.
Here is what I have:
(^([0])$)|(^([1-9][0-9]{0-9})$)
This reg exp looks a little crazy, I've been trying a lot of different things and making even more crazier and crazier.
For a range of possibilities, you use a comma, not a hyphen.
(^([0])$)|(^([1-9][0-9]{0,9})$)
However, your regex can be shortened to:
^(0|[1-9][0-9]{0,9})$
offering the faster, non-Regex approach:
static void Main(string[] args
{
string str = "12";
long test;
if(str.Length <= 10
&& long.TryParse(str, out test)
&& test >= 0)
{
//valid
}
}
Related
Okay, so after looking around here on SO, I have found a solution that meets about 95% of my requirement, although I believe it may need to be redone at this point.
ISSUE
Say I have a value range supplied as "1000 - 1009 ABC1 ABC SOMETHING ELSE" where I just need the 1000 - 1009 part. I need to be able to remove excess characters from the string supplied, even if they truly are accepted characters, but only if they are part of secondary strings with text. (Sorry if that description seems odd, my mind isn't full power today.)
CURRENT SOLUTION
I currently have a simple method utilizing Linq to return only accepted characters, however this will return "1000 - 10091" which is not the range I am needing. I've thought about looping through the strings individual characters and comparing to previous characters as I go using IsDigit and IsLetter to my advantage, but then comes the issue of replacing the unacceptable characters or removing them. I think if I gave it a day or two I could figure it out with a clear mind, but it needs to be done by the end of the day, and I am banging my head against the keyboard.
void RemoveExcessText(ref string val) {
string allowedChars = "0123456789-+>";
val = new string(val.Where(c => allowedChars.Contains(c)).ToArray());
}
// Alternatively?
char previousChar = ' ';
for (int i = 0; i < val.Length; i++) {
if (char.IsLetter(val[i])) {
previousChar = val[i];
val.Remove(i, 1);
} else if (char.IsDigit(val[i])) {
if (char.IsLetter(previousChar)) {
val.Remove(i, 1);
}
}
}
But how do I calculate white space and leave in the +, -, and > charactrers? I am losing my mind on this one today.
Why not use a regular expression?
Regex.Match("1000 - 1009 ABC1 ABC SOMETHING ELSE", #"^(\d+)([\s\-]+)(\d+)");
Should give you what you want
I made a fiddle
You use a regular expression with a capturing group:
Regex r = new Regex("^(?<v>[-0-9 ]+?)");
This means "from the start of the input string (^) match [0 to 9 or space or hyphen] and keep going for as many occurrences of these characters as are available (+?) and store it into variable v (?)"
We get it out like this:
r.Matches(input)[0].Groups["v"].Value
Note though that if the input string doesn't match, the match collection will be 0 long and a call to [0] will crash. To this end you might want to robust it up with some extra error checking:
MatchCollection mc = r.Matches(input);
if(mc.Length > 0)
MessageBox.Show(mc[0].Groups["v"].Value;
You could match this with a regular expression. \d{1,4} means match a decimal digit at least once up to 4 times. Followed by space, hyphen, space, and 1 to 4 digits again, then anything else. Only the part inside parenthesis is output in your results.
using System;
using System.Text.RegularExpressions;
public class Program
{
public static void Main()
{
var pattern = #"(^\d{1,4} - \d{1,4}).*";
string input = ("1000 - 1009 ABC1 ABC SOMETHING ELSE");
string replacement = "$1";
string result = Regex.Replace(input, pattern, replacement);
Console.WriteLine(result);
}
}
https://dotnetfiddle.net/cZGlX4
I am working on a window form which accepts certain range of value as input. So far, I could only find the range between 0 and 20000.
(20000|[0-9]|0[1-9]|[1-9]\d{0,3})$
Can somebody kindly help me with finding the range between 0.0 and 20479.0 (including decimals)?
As comments suggest, regex is far from ideal in these cases. It can be done though, but get quite complex.
^(?:(?:1?\d{1,4}|20[0-3]\d\d|204[0-6]\d|2047[0-8])(?:\.\d+)?|20479(?:\.0+)?)$
This does it using two outer alternations - one to match the maximum number and optionally any number of zeroes as decimals. The other (first) has several sub-alternations matching the maximum for the different digits, and allowing an optional decimal point and decimals.
1?\d{1,4} Matches 0-19999
20[0-3]\d\d Matches 20000-20399
204[0-6]\d Matches 20400-20469
2047[0-8] Matches 20470-20478
See it here at regex101.
Here is a suggestion that allows numbers between 0 and 20479 with decimals:
^(0?[0-9]{0,4}(?:\.\d+)?|1\d{4}(?:\.\d+)?|20[0-4][0-7][0-8](?:\.\d+)?|20479(?:\.[0-7])?)$
As you can see, it is a bit complex, you may not want to do it with a regex.
Demo on regex101
Explanation
(0?[0-9]{0,4}(?:\.\d+)? between 0.0 and 9999.99 (decimals are optional)
1\d{4}(?:\.\d+)? between 10000.0 and 19999.99 (decimals are optional)
20[0-4][0-7][0-8](?:\.\d+)? between 20000.0 and 2048.99 (decimals are optional)
20479(?:\.[0-7])? between 20479 and 20479.7
Update: Without decimals, you can use:
^(0?[0-9]{0,4}|1\d{4}|20[0-4][0-7][0-8]|20479$
If you expect only integers (.0 at the end) you could try this
Mask is
^((1?[0-9]{0,4})|((20(([0-3][0-9]{0,2})|(4[0-7][0-9])))))$
If you need .0 at the end add \.0 before $. If you need double/decimal than precision/range would be required.
Why would you use a regex that'll be hardly maintainable when you can use real code:
public bool IsValid(string input = "")
{
double inputParsed;
if (!double.TryParse(input, out inputParsed))
return false;
if(inputParsed < 0 || inputParsed > 20479)
return false;
return true;
}
Using regex get two numbers before and after the point.
Then check the numbers to hit the range.
var list = new List<string> { "VB0.0", "VB20479.0", "VB20479.7", "VB20480.0", "VB010000.0", "VB0.8", "VBx.y" };
string pattern = #"(\d+)\.(\d+)";
foreach (var input in list)
{
var m = Regex.Match(input, pattern);
if (m.Success)
{
string value1 = m.Groups[1].Value;
string value2 = m.Groups[2].Value;
bool result = value1.Length <= 5 && int.Parse(value1) <= 20479
&& value2.Length <= 1 && int.Parse(value2) <= 7;
Console.WriteLine(result);
}
else Console.WriteLine(false);
}
I have had a difficult time wrapping my head around regular expressions. In the following code, I used a Regex to determine if the data passed was a 1 to 3 digit number. The expression worked if the data started with a number (ex. "200"), but also passed if the data had a letter not in the first digit (ex. "3A5"). I managed to handle the error with the INT32.TryParse() method, but it seems there should be an easier way.
if (LSK == MainWindow.LSK6R)
{
int ci;
int length = SP_Command.Length;
if (length > 3) return MainWindow.ENTRY_OUT_OF_RANGE; //Cannot be greater than 999
String pattern = #"[0-9]{1,3}"; //RegEx pattern for 1 to 3 digit number
if (Regex.IsMatch(SP_Command, pattern)) //Does not check for ^A-Z. See below.
{
bool test = Int32.TryParse(SP_Command, out ci); //Trying to parse A-Z. Only if
if (test) //it no letter will it succeed
{
FlightPlan.CostIndex = ci; //Update the flightplan CI
CI.Text = ci.ToString(); //Update the Init page
}
else return MainWindow.FORMAT_ERROR; //It contained a letter
}
else return MainWindow.FORMAT_ERROR; //It didn't fit the RegEx
}
Regex.IsMatch searches the input string for the pattern (and thus returns true for 3A5 because it finds 3).
You should also include start (^) and end ($) of string:
String pattern = #"^[0-9]{1,3}$";
Adding line begin/end should help.
^[0-9]{1,3}$
I got the following :
01.05.03
I need to convert that to 1.5.3
The problem is I cannot only trim the 0 because if I got :
01.05.10
I need to convert that to 1.5.10
So, what's the better way to solve that problem ? Regex ? If so, any regex example doing that ?
Expanding on the answer of #FrustratedWithFormsDesigner:
string Strip0s(string s)
{
return string.Join<int>(".", from x in s.Split('.') select int.Parse(x));
}
Regex-replace
(?<=^|\.)0+
with the empty string. The regex is:
(?<= # begin positive look-behind (i.e. "a position preceded by")
^|\. # the start of the string or a literal dot †
) # end positive look-behind
0+ # one or more "0" characters
† note that not all regex flavors support variable-length look-behind, but .NET does.
If you expect this kind of input: "00.03.03" and want to to keep the leading zero in this case (like "0.3.3"), use this expression instead:
(?<=^|\.)0+(?=\d)
and again replace with the empty string.
From the comments (thanks Kobi): There is a more concise expression that does not require look-behind and is equivalent to my second suggestion:
\b0+(?=\d)
which is
\b # a word boundary (a position between a word char and a non-word char)
0+ # one or more "0" characters
(?=\d) # positive look-ahead: a position that's followed by a digit
This works because the 0 happens to be a word character, so word boundaries can be used to find the first 0 in a row. It is a more compatible expression, because many regex flavors do not support variable-length look-behind, and some (like JavaScript) no look-behind at all.
You could split the string on ., then trim the leading 0s on the results of the split, then merge them back together.
I don't know of a way to do this in a single operation, but you could write a function that hides this and makes it look like a single operation. ;)
UPDATE:
I didn't even think of the other guy's regex. Yeah, that will probably do it in a single operation.
Here's another way you could do what FrustratedWithFormsDesigner suggests:
string s = "01.05.10";
string s2 = string.Join(
".",
s.Split('.')
.Select(str => str.TrimStart('0'))
.ToArray()
);
This is almost the same as dtb's answer, but doesn't require that the substrings be valid integers (it would also work with, e.g., "000A.007.0HHIMARK").
UPDATE: If you'd want any strings consisting of all 0s in the input string to be output as a single 0, you could use this:
string s2 = string.Join(
".",
s.Split('.')
.Select(str => TrimLeadingZeros(str))
.ToArray()
);
public static string TrimLeadingZeros(string text) {
int number;
if (int.TryParse(text, out number))
return number.ToString();
else
return text.TrimStart('0');
}
Example input/output:
00.00.000A.007.0HHIMARK // input
0.0.A.7.HHIMARK // output
There's also the old-school way which probably has better performance characteristics than most other solutions mentioned. Something like:
static public string NormalizeVersionString(string versionString)
{
if(versionString == null)
throw new NullArgumentException("versionString");
bool insideNumber = false;
StringBuilder sb = new StringBuilder(versionString.Length);
foreach(char c in versionString)
{
if(c == '.')
{
sb.Append('.');
insideNumber = false;
}
else if(c >= '1' && c <= '9')
{
sb.Append(c);
insideNumber = true;
}
else if(c == '0')
{
if(insideNumber)
sb.Append('0');
}
}
return sb.ToString();
}
string s = "01.05.10";
string newS = s.Replace(".0", ".");
newS = newS.StartsWith("0") ? newS.Substring(1, newS.Length - 1) : newS;
Console.WriteLine(newS);
NOTE: You will have to thoroughly check for possible input combination.
This looks like it is a date format, if so I would use Date processing code
DateTime time = DateTime.Parse("01.02.03");
String newFormat = time.ToString("d.M.yy");
or even better
String newFormat = time.ToShortDateString();
which will respect you and your clients culture setting.
If this data is not a date then don't use this :)
I had a similar requirement to parse a string with street adresses, where some of the house numbers had leading zeroes and I needed to remove them while keeping the rest of the text intact, so I slightly edited the accepted answer to meet my requirements, maybe someone finds it useful. Basically doing the same as accepted answer, with the difference that I am checking if the string part can be parsed as an integer, and defaulting to the string value when false;
string Strip0s(string s)
{
int outputValue;
return
string.Join(" ",
from x in s.Split(new[] { ' ' })
select int.TryParse(x, out outputValue) ? outputValue.ToString() : x);
}
Input: "Islands Brygge 34 B 07 TV"
Output: "Islands Brygge 34 B 7 TV"
what's the quickest way to extract a 5 digit number from a string in c#.
I've got
string.Join(null, System.Text.RegularExpressions.Regex.Split(expression, "[^\\d]"));
Any others?
The regex approach is probably the quickest to implement but not the quickest to run. I compared a simple regex solution to the following manual search code and found that the manual search code is ~2x-2.5x faster for large input strings and up to 4x faster for small strings:
static string Search(string expression)
{
int run = 0;
for (int i = 0; i < expression.Length; i++)
{
char c = expression[i];
if (Char.IsDigit(c))
run++;
else if (run == 5)
return expression.Substring(i - run, run);
else
run = 0;
}
return null;
}
const string pattern = #"\d{5}";
static string NotCached(string expression)
{
return Regex.Match(expression, pattern, RegexOptions.Compiled).Value;
}
static Regex regex = new Regex(pattern, RegexOptions.Compiled);
static string Cached(string expression)
{
return regex.Match(expression).Value;
}
Results for a ~50-char string with a 5-digit string in the middle, over 10^6 iterations, latency per call in microseconds (smaller number is faster):
Simple search: 0.648396us
Cached Regex: 2.1414645us
Non-cached Regex: 3.070116us
Results for a ~40K string with a 5-digit string in the middle over 10^4 iterations, latency per call in microseconds (smaller number is faster):
Simple search: 423.801us
Cached Regex: 1155.3948us
Non-cached Regex: 1220.625us
A little surprising: I would have expected Regex -- which is compiled to IL -- to be comparable to the manual search, at least for very large strings.
Use a regular expression (\d{5}) to find the occurrence(s) of the 5 digit number in the string and use int.Parse or decimal.Parse on the match(s).
In the case where there is only one number in text.
int? value = null;
string pat = #"\d{5}"
Regex r = new Regex(pat);
Match m = r.Match(text);
if (m.Success)
{
value = int.Parse(m.Value);
}
Do you mean convert a string to a number? Or find the first 5 digit string and then make it a number? Either way, you'll probably be using decimal.Parse or int.Parse.
I'm of the opinion that Regular Expressions are the wrong approach. A more efficient approach would simply to walk through the string looking for a digit, and then advancing 4 characters and seeing if they are all digits. If they are, you've got your substring. It's not as robust, no, but it doesn't have the overhead either.
Don't use a regular expression at all. It's way more powerful than you need - and that power is likely to hit performance.
If you can give more details of what you need it to do, we can write the appropriate code... (Test cases would be ideal.)
If the numbers exist with other characters regular expressions are a good solution.
EG: ([0-9]{5})
will match - asdfkki12345afdkjsdl, 12345adfaksk, or akdkfa12345
If you have a simple test case like "12345" or even "12345abcd" don't use regex at all. They are not known by they speed.
For most strings a brute force method is going to be quicker than a RegEx.
A fairly noddy example would be:
string strIWantNumFrom = "qweqwe23qeeq3eqqew9qwer0q";
int num = int.Parse(
string.Join( null, (
from c in strIWantNumFrom.ToCharArray()
where c == '1' || c == '2' || c == '3' || c == '4' || c == '5' ||
c == '6' || c == '7' || c == '8' || c == '9' || c == '0'
select c.ToString()
).ToArray() ) );
No doubt there are much quicker ways, and lots of optimisations that depend on the exact format of your string.
This might be faster...
public static string DigitsOnly(string inVal)
{
char[] newPhon = new char[inVal.Length];
int i = 0;
foreach (char c in inVal)
if (c.CompareTo('0') > 0 && c.CompareTo('9') < 0)
newPhon[i++] = c;
return newPhon.ToString();
}
if you want to limit it to at most five digits, then
public static string DigitsOnly(string inVal)
{
char[] newPhon = new char[inVal.Length];
int i = 0;
foreach (char c in inVal)
if (c.CompareTo('0') > 0 && c.CompareTo('9') < 0 && i < 5)
newPhon[i++] = c;
return newPhon.ToString();
}