I'm not sure how to accomplish this with a regular expression (or if I can; I'm new to regex). I have an angle value the user will type in and I'm trying to validate the entry. It is in the form degrees-minutes-seconds. The problem I'm having, is that if the user mistypes the seconds portion, I have to catch that error, but my match for degrees-minutes is a success.
我不确定如何使用正则表达式来实现这一点(或者如果可以的话;我是正则表达式的新手)。我有一个用户将输入的角度值,我正在尝试验证该条目。它的形式为度 - 分 - 秒。我遇到的问题是,如果用户错误输入秒部分,我必须捕获该错误,但我的度数 - 分钟的匹配是成功的。
Perhaps the method will explain better:
也许这种方法会更好地解释:
private Boolean isTextValid(String _angleValue) {
Regex _degreeMatchPattern = new Regex("0*[1-9]");
Regex degreeMinMatchPattern = new Regex("(0*[0-9]-{1}0*[0-9]){1}");
Regex degreeMinSecMatchPattern = new Regex("0*[0-9]-{1}0*[0-9]-{1}0*[0-9]");
Match _degreeMatch, _degreeMinMatch, _degreeMinSecMatch;
_degreeMinSecMatch = degreeMinSecMatchPattern.Match(_angleValue);
if (_degreeMinSecMatch.Success)
return true;
_degreeMinMatch = degreeMinMatchPattern.Match(_angleValue);
if (_degreeMinMatch.Success)
return true;
_degreeMatch = _degreeMatchPattern.Match(_angleValue);
if (_degreeMatch.Success)
return true;
return false;
}
}
I want to check for degrees-minutes if the degrees-minutes-seconds match is unsuccessful, but only if the user didn't enter any seconds data. Can I do this via regex, or do I need to parse the string and evaluate each portion separately? Thanks.
如果度 - 分 - 秒匹配不成功,我想检查度 - 分钟,但仅当用户没有输入任何秒数据时。我可以通过正则表达式执行此操作,还是需要解析字符串并单独评估每个部分?谢谢。
EDIT: Sample data would be 45-23-10 as correct data. The problem is 45-23 is also valid data; the 0 seconds is understood. So if the user types 45-23-1= on accident, the degreeMinMatchPattern regex in my code will match succesfully, even though it is invalid.
编辑:样本数据将是45-23-10作为正确的数据。问题是45-23也是有效数据; 0秒被理解。因此,如果用户在事故中键入45-23-1 =,我的代码中的degreeMinMatchPattern正则表达式将成功匹配,即使它无效。
Second EDIT: Just to make it clear, the minutes and second portions are both optional. The user can type 45 and that is valid.
第二次编辑:为了说清楚,分钟和第二部分都是可选的。用户可以键入45,这是有效的。
5 个解决方案
#1
2
First off, a character in a regex is matched once by default, so {1} is redundant.
首先,默认情况下,正则表达式中的字符匹配一次,因此{1}是多余的。
Second, since you can apparently isolate this value (you prompt for just this value, instead of having to look for it in a paragraph of entered data) you should include ^ and $ in your string, to enforce that the string should contain ONLY this pattern.
其次,既然你可以显然隔离这个值(你只提示这个值,而不是必须在输入的数据段中查找它),你应该在你的字符串中包含^和$,以强制该字符串只包含这个模式。
Try "^\d{1,3}-\d{1,2}(-\d{1,2})?$".
试试“^ \ d {1,3} - \ d {1,2}( - \ d {1,2})?$”。
Breaking it down: ^ matches the beginning of the string. \d matches any single decimal character, and then behind that you're specifying {1,3} which will match a set of one to three occurrences of any digit. Then you're looking for one dash, then a similar decimal pattern but only one or two times. The last term is enclosed in parenthesis so we can group the characters. Its form is similar to the first two, then there's a ? which marks the preceding character group as optional. The $ at the end indicates that the input should end. Given this, it will match 222-33-44 or 222-33, but not 222-3344 or 222-33-abc.
分解:^匹配字符串的开头。 \ d匹配任何单个十进制字符,然后在你指定{1,3}之后,它将匹配任何数字的一到三次出现的集合。然后你正在寻找一个破折号,然后是一个类似的小数模式,但只有一两次。最后一个术语括在括号中,因此我们可以对字符进行分组。它的形式类似于前两个,那么有一个?它将前面的字符组标记为可选。最后的$表示输入应该结束。鉴于此,它将匹配222-33-44或222-33,但不匹配222-3344或222-33-abc。
Keep in mind there are additional rules you might want to incorporate. For instance, seconds can be expressed as a decimal (if you want a resolution smaller than one second). You would need to optionally expect the decimal point and one or more additional digits. Also, you probably have a maximum degree value; the above regex will match the maximum integer DMS value of 359-59-59, however it will also match 999-99-99 which is not valid. You can limit the maximum value using regex (for example "(3[0-5]\d|[1-2]\d{2}|\d{1,2})" will match any number from 0 to 359, by matching a 3, then 0-5, then 0-9, OR any 3-digit number starting with 1 or 2, OR any two-digit number), but as the example shows the regex will get long and messy, so document it well in code as to what you're doing.
请记住,您可能希望合并其他规则。例如,秒可以表示为小数(如果您希望分辨率小于1秒)。您可能需要选择小数点和一个或多个附加数字。此外,您可能拥有最大学位值;上述正则表达式将匹配最大整数DMS值359-59-59,但它也将匹配999-99-99,这是无效的。您可以使用正则表达式限制最大值(例如“(3 [0-5] \ d | [1-2] \ d {2} | \ d {1,2})”将匹配0到359之间的任何数字,通过匹配3,然后是0-5,然后是0-9,或任何以1或2开头的3位数字,或任何两位数的数字),但正如示例所示,正则表达式会变得冗长而混乱,所以在代码中记录好你正在做的事情。
#2
4
You can specify "this part of the pattern must match at least 3 times" using the {m,}
syntax. Since there are hyphens between each component, specify the first part separately, and then each hyphen-digit combination can be grouped together after:
您可以使用{m,}语法指定“模式的此部分必须至少匹配3次”。由于每个组件之间都有连字符,请分别指定第一个部分,然后在以下各项之后将每个连字符组合组合在一起:
`[0-9](-[0-9]){2,}`
You also can shorten [0-9]
to \d
: \d(-\d){2,}
您还可以将[0-9]缩短为\ d:\ d( - \ d){2,}
#3
1
Maybe you would do better to just parse the input out and check is piece separately.
也许你会更好地解析输入并单独检查。
#4
0
I'm not sure I understand correctly, but I think
我不确定我是否理解正确,但我想
(?<degrees>0*[0-9])-?(?<minutes>0*[0-9])(?:-?(?<seconds>0*[0-9]))?$
might work.
可能有用。
But this is quite ambiguous; also I'm wondering why you're only allowing single-digit degree/minute/second values. Please show some examples you do and don't want to match.
但这很模糊;我也想知道为什么你只允许一位数度/分/秒值。请显示一些您不喜欢的例子。
#5
0
Maybe you should to try something like this and test for empty/invalid groups:
也许你应该尝试这样的事情并测试空/无效组:
Regex degrees = new Regex(
@"(?<degrees>\d+)(?:-(?<minutes>\d+))?(?:-(?<seconds>\d+))?");
string[] samples = new []{ "123", "123-456", "123-456-789" };
foreach (var sample in samples)
{
Match m = degrees.Match(sample);
if(m.Success)
{
string degrees = m.Groups["degrees"].Value;
string minutes = m.Groups["minutes"].Value;
string seconds = m.Groups["seconds"].Value;
Console.WriteLine("{0}°{1}'{2}\"", degrees,
String.IsNullOrEmpty(minutes) ? "0" : minutes,
String.IsNullOrEmpty(seconds) ? "0" : seconds
);
}
}
#1
2
First off, a character in a regex is matched once by default, so {1} is redundant.
首先,默认情况下,正则表达式中的字符匹配一次,因此{1}是多余的。
Second, since you can apparently isolate this value (you prompt for just this value, instead of having to look for it in a paragraph of entered data) you should include ^ and $ in your string, to enforce that the string should contain ONLY this pattern.
其次,既然你可以显然隔离这个值(你只提示这个值,而不是必须在输入的数据段中查找它),你应该在你的字符串中包含^和$,以强制该字符串只包含这个模式。
Try "^\d{1,3}-\d{1,2}(-\d{1,2})?$".
试试“^ \ d {1,3} - \ d {1,2}( - \ d {1,2})?$”。
Breaking it down: ^ matches the beginning of the string. \d matches any single decimal character, and then behind that you're specifying {1,3} which will match a set of one to three occurrences of any digit. Then you're looking for one dash, then a similar decimal pattern but only one or two times. The last term is enclosed in parenthesis so we can group the characters. Its form is similar to the first two, then there's a ? which marks the preceding character group as optional. The $ at the end indicates that the input should end. Given this, it will match 222-33-44 or 222-33, but not 222-3344 or 222-33-abc.
分解:^匹配字符串的开头。 \ d匹配任何单个十进制字符,然后在你指定{1,3}之后,它将匹配任何数字的一到三次出现的集合。然后你正在寻找一个破折号,然后是一个类似的小数模式,但只有一两次。最后一个术语括在括号中,因此我们可以对字符进行分组。它的形式类似于前两个,那么有一个?它将前面的字符组标记为可选。最后的$表示输入应该结束。鉴于此,它将匹配222-33-44或222-33,但不匹配222-3344或222-33-abc。
Keep in mind there are additional rules you might want to incorporate. For instance, seconds can be expressed as a decimal (if you want a resolution smaller than one second). You would need to optionally expect the decimal point and one or more additional digits. Also, you probably have a maximum degree value; the above regex will match the maximum integer DMS value of 359-59-59, however it will also match 999-99-99 which is not valid. You can limit the maximum value using regex (for example "(3[0-5]\d|[1-2]\d{2}|\d{1,2})" will match any number from 0 to 359, by matching a 3, then 0-5, then 0-9, OR any 3-digit number starting with 1 or 2, OR any two-digit number), but as the example shows the regex will get long and messy, so document it well in code as to what you're doing.
请记住,您可能希望合并其他规则。例如,秒可以表示为小数(如果您希望分辨率小于1秒)。您可能需要选择小数点和一个或多个附加数字。此外,您可能拥有最大学位值;上述正则表达式将匹配最大整数DMS值359-59-59,但它也将匹配999-99-99,这是无效的。您可以使用正则表达式限制最大值(例如“(3 [0-5] \ d | [1-2] \ d {2} | \ d {1,2})”将匹配0到359之间的任何数字,通过匹配3,然后是0-5,然后是0-9,或任何以1或2开头的3位数字,或任何两位数的数字),但正如示例所示,正则表达式会变得冗长而混乱,所以在代码中记录好你正在做的事情。
#2
4
You can specify "this part of the pattern must match at least 3 times" using the {m,}
syntax. Since there are hyphens between each component, specify the first part separately, and then each hyphen-digit combination can be grouped together after:
您可以使用{m,}语法指定“模式的此部分必须至少匹配3次”。由于每个组件之间都有连字符,请分别指定第一个部分,然后在以下各项之后将每个连字符组合组合在一起:
`[0-9](-[0-9]){2,}`
You also can shorten [0-9]
to \d
: \d(-\d){2,}
您还可以将[0-9]缩短为\ d:\ d( - \ d){2,}
#3
1
Maybe you would do better to just parse the input out and check is piece separately.
也许你会更好地解析输入并单独检查。
#4
0
I'm not sure I understand correctly, but I think
我不确定我是否理解正确,但我想
(?<degrees>0*[0-9])-?(?<minutes>0*[0-9])(?:-?(?<seconds>0*[0-9]))?$
might work.
可能有用。
But this is quite ambiguous; also I'm wondering why you're only allowing single-digit degree/minute/second values. Please show some examples you do and don't want to match.
但这很模糊;我也想知道为什么你只允许一位数度/分/秒值。请显示一些您不喜欢的例子。
#5
0
Maybe you should to try something like this and test for empty/invalid groups:
也许你应该尝试这样的事情并测试空/无效组:
Regex degrees = new Regex(
@"(?<degrees>\d+)(?:-(?<minutes>\d+))?(?:-(?<seconds>\d+))?");
string[] samples = new []{ "123", "123-456", "123-456-789" };
foreach (var sample in samples)
{
Match m = degrees.Match(sample);
if(m.Success)
{
string degrees = m.Groups["degrees"].Value;
string minutes = m.Groups["minutes"].Value;
string seconds = m.Groups["seconds"].Value;
Console.WriteLine("{0}°{1}'{2}\"", degrees,
String.IsNullOrEmpty(minutes) ? "0" : minutes,
String.IsNullOrEmpty(seconds) ? "0" : seconds
);
}
}