匹配模式[0-9] - [0-9] - [0-9],但没有匹配[0-9] - [0-9]

时间:2010-09-27 17:15:43

标签: c# regex

我不知道如何使用正则表达式来实现这一点(或者如果可以的话;我是正则表达式的新手)。我有一个用户将输入的角度值,我正在尝试验证该条目。它的形式为度 - 分 - 秒。我遇到的问题是,如果用户错误输入秒部分,我必须捕获该错误,但我的度数 - 分钟是成功的。

也许这种方法会更好地解释:

    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;
    }
}

如果度 - 分 - 秒匹配不成功,我想检查度 - 分钟,但仅当用户没有输入任何秒数据时。我可以通过正则表达式执行此操作,还是需要解析字符串并单独评估每个部分?感谢。

编辑:样本数据将是45-23-10作为正确数据。问题是45-23也是有效数据; 0秒被理解。因此,如果用户在事故中键入45-23-1 =,我的代码中的degreeMinMatchPattern正则表达式将成功匹配,即使它是无效的。

第二次编辑:为了说清楚,分钟和第二部分都是可选的。用户可以键入45,这是有效的。

5 个答案:

答案 0 :(得分:4)

您可以使用{m,}语法指定“模式的此部分必须至少匹配3次”。由于每个组件之间都有连字符,请分别指定第一个部分,然后在每个连字符组合后将其组合在一起:

`[0-9](-[0-9]){2,}`

您还可以将[0-9]缩短为\d\d(-\d){2,}

答案 1 :(得分:2)

首先,默认情况下,正则表达式中的字符匹配一次,因此{1}是多余的。

其次,既然你可以明显地隔离这个值(你只提示这个值,而不是在输入数据的段落中查找它),你应该在你的字符串中包含^和$,以强制字符串应该仅包含此模式。

尝试“^ \ d {1,3} - \ d {1,2}( - \ d {1,2})?$”。

分解:^匹配字符串的开头。 \ d匹配任何单个十进制字符,然后在您指定{1,3}之后,它将匹配任意数字的一到三次出现的集合。然后你正在寻找一个破折号,然后是一个类似的小数模式,但只有一两次。最后一个术语括在括号中,因此我们可以对字符进行分组。它的形式类似于前两个,那么有一个?它将前面的字符组标记为可选。最后的$表示输入应该结束。鉴于此,它将匹配222-33-44或222-33,但不匹配222-3344或222-33-abc。

请注意,您可能希望合并其他规则。例如,秒可以表示为小数(如果您希望分辨率小于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 :(得分:1)

也许你会更好地解析输入并单独检查。

答案 3 :(得分:0)

我不确定我是否理解正确,但我认为

(?<degrees>0*[0-9])-?(?<minutes>0*[0-9])(?:-?(?<seconds>0*[0-9]))?$

可能有用。

但这很模糊;我也想知道为什么你只允许一位数度/分/秒值。请展示一些您不喜欢的例子。

答案 4 :(得分:0)

也许你应该尝试这样的事情并测试空/无效组:

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
        );
    }
}