1

我必须有格式为x:y的字符串,其中xy必须是五位数字(填充零)并且x <= y

例子:

00515:02152

什么正则表达式会匹配这种格式?

如果可能,请简要说明解决方案以帮助我学习。

编辑:为什么我需要正则表达式?我编写了一个通用工具,它接受输入并根据配置文件对其进行验证。突然出现一个意外要求,要求我以我显示的格式验证字符串(使用配置文件)。我希望使用我编写的现有配置框架来解决这个问题,因为拆分和解析超出了这个工具的范围。对于这样一个突出的要求,我不介意有一些非正统/凌乱的正则表达式,只要它不是 10000 行长。任何使用正则表达式的智能解决方案都值得赞赏!谢谢。

4

8 回答 8

7

描述

此表达式将验证第一个 5 位数字是否小于第二个 5 位数字,其中零填充的 5 位数字位于:分隔字符串中,格式为01234:23456.

^
(?:
(?=0....:[1-9]|1....:[2-9]|2....:[3-9]|3....:[4-9]|4....:[5-9]|5....:[6-9]|6....:[7-9]|7....:[8-9]|8....:[9])
|(?=(.)(?:0...:\1[1-9]|1...:\1[2-9]|2...:\1[3-9]|3...:\1[4-9]|4...:\1[5-9]|5...:\1[6-9]|6...:\1[7-9]|7...:\1[8-9]|8...:\1[9]))
|(?=(..)(?:0..:\2[1-9]|1..:\2[2-9]|2..:\2[3-9]|3..:\2[4-9]|4..:\2[5-9]|5..:\2[6-9]|6..:\2[7-9]|7..:\2[8-9]|8..:\2[9]))
|(?=(...)(?:0.:\3[1-9]|1.:\3[2-9]|2.:\3[3-9]|3.:\3[4-9]|4.:\3[5-9]|5.:\3[6-9]|6.:\3[7-9]|7.:\3[8-9]|8.:\3[9]))
|(?=(....)(?:0:\4[1-9]|1:\4[2-9]|2:\4[3-9]|3:\4[4-9]|4:\4[5-9]|5:\4[6-9]|6:\4[7-9]|7:\4[8-9]|8:\4[9]))
)
\d{5}:\d{5}$

现场演示: http ://www.rubular.com/r/w1QLZhNoEa

请注意,这是使用x忽略所有空格并允许注释的选项,如果您不使用此选项,x则表达式将需要全部在一行

在此处输入图像描述

于 2013-07-19T16:02:23.837 回答
5

您要识别的语言是有限的,所以最简单的方法就是列出所有用“或”分隔的案例。你想要的正则表达式是:

(00000:[00000|00001| ... 99999])|  ...  |(99998:[99998|99999])|(99999:99999)

该正则表达式将有数十亿个字符长并且需要相当长的时间来执行,但它正是您所要求的:与所述语言匹配的正则表达式。

显然这是不切实际的。现在是否清楚为什么正则表达式是这项工作的错误工具?使用正则表达式来匹配 5 位数字 - 冒号 - 5 位数字,然后一旦知道有,就拆分字符串并将两组数字转换为可以比较的整数。

于 2013-07-19T15:17:17.153 回答
2

x <= y。

好吧,你使用了错误的工具。真的,正则表达式在这里帮不了你。或者即使你得到了一个解决方案,那也太复杂了,而且太难扩展了。

Regex 是一种文本处理工具,用于匹配常规语言中的模式。在语义方面它非常弱。它无法识别给定字符串中的含义。就像在您给定的条件下一样,要符合条件,您需要了解它们的数值。x <= y

例如,它可以匹配序列中的数字,或数字和字符的混合,但它不能做的是 -

  • 匹配大于15和小于1245的数字,或
  • 匹配作为给定两个日期之间的日期的模式

因此,无论何时匹配模式,都涉及将语义应用于匹配的字符串,Regex 不是一个选项。

这里适当的方法是对split字符串 on colon,然后比较数字。对于前导零,您可以找到一些解决方法。

于 2013-07-19T13:50:16.637 回答
1

您通常*不能使用正则表达式执行此操作。您可以使用正则表达式匹配模式并提取数字,然后比较代码中的数字。

例如,匹配这种格式(不比较数字)并获取您可以使用的数字:

^(\d{5}):(\d{5})\z

*)在这种情况下你可能可以(因为数字总是 5 位数字和零填充,但这不会很好。

于 2013-07-19T13:49:06.750 回答
0

你应该这样做:

bool IsCorrect(string s)
{
    string[] split = s.split(':');
    int number1, number2;
    if (split.Length == 2 && split[0].Length == 5 && split[1].Length == 5)
    {
        if (int.TryParse(split[0], out number1) && int.TryParse(split[1], out number2) && number1 <= number2)
        {
            return true;
        }
    }
    return false;
}

使用正则表达式,您无法进行比较以查看一个数字是否大于另一个数字。

于 2013-07-19T13:53:18.830 回答
0

让我向你展示一个很好的例子,说明为什么你不应该尝试这样做。这是一个(几乎)做同样工作的正则表达式。

https://gist.github.com/anonymous/ad74e73f0350535d09c1

原始文件:

https://gist.github.com/anonymous/ad74e73f0350535d09c1/raw/03ea835b0e7bf7ac3c5fb6f9c7e934b83fb09d95/gistfile1.txt

除了它只是3位数。对于 4,生成这些的程序失败并显示OutOfMemoryException. gcAllowVeryLargeObjects启用。它一直持续到 5GB,直到它崩溃。您不希望您的大部分应用程序都是正则表达式,对吗?

不是正则表达式的工作。

于 2013-07-19T14:18:57.500 回答
0

这是一个两步过程,因为正则表达式是文本解析器而不是分析器。但是话虽如此,正则表达式非常适合验证我们是否具有 5:5 数字模式,并且此正则表达式模式将确定我们是否具有该形状因子 \d\d​​\d\d\d:\d\d\d\d \d 对。如果未找到该外形尺寸,则匹配失败并且整个验证失败。如果有效,我们可以使用 regex/linq 解析出数字,然后检查其有效性。

此代码将在进行检查的方法中

var data = "00515:02151";
var pattern = @"
^               # starting from the beginning of the string...
(?=[\d:]{11})   # Is there is a string that is at least 11 characters long with only numbers and a ;, fail if not
(?=\d{5}:\d{5}) # Does it fall into our pattern? If not fail the match
((?<Values>[^:]+)(?::?)){2}  
";

// IgnorePatternWhitespace only allows us to comment the pattern, it does not affect the regex parsing
var result = Regex.Matches(data, pattern, RegexOptions.IgnorePatternWhitespace)
                  .OfType<Match>()
                  .Select (mt =>  mt.Groups["Values"].Captures
                                                .OfType<Capture>()
                                                .Select (cp => int.Parse(cp.Value)))
                  .FirstOrDefault();

// Two values at this point 515, 2151

bool valid = ((result != null) && (result.First () < result.Last ()));

Console.WriteLine (valid); // True
于 2013-07-19T14:36:48.657 回答
-1

使用 Javascript 这可以工作。

    var string = "00515:02152";

    string.replace(/(\d{5})\:(\d{5})/, function($1,$2,$3){ 
         return (parseInt($2)<=parseInt($3))?$1:null;
    });

小提琴http://jsfiddle.net/VdzF7/

于 2013-07-19T17:14:01.503 回答