Java正则表达式到.NET

时间:2011-11-11 16:02:07

标签: java .net regex

我正在尝试将以下正则表达式从Java转换为.NET:

    (?i:(?:([^\d,]+?)\W+\b((?:CA|SD|SC|CT|DC)\b)?\W*)?(\d{5}(?:[- ]\d{3,4})?)?)

当我针对以下字符串运行匹配时:

Mountain View, CA 94043

使用Java中的Pattern和Matcher对象,它使用以下值填充四个组:

    "Mountain View, CA 94043"
    "Mountain View"
    "CA"
    "94043"

但是,在.NET中,有两个匹配项。第一个匹配使用以下值填充四个组:

    "Mountain "(there is a space on the end of group 0)
    "Mountain"
    ""
    ""

第二个匹配使用以下值填充三个组:

    "View, CA 94043"
    "View"
    "CA"
    "94043"

我也尝试使用RegexBuddy同时使用Java和.NET模式,在RegexBuddy中,两种模式都像.NET版本一样。

谢谢大家!

1 个答案:

答案 0 :(得分:4)

^添加到模式的开头,并在其末尾添加$以分别匹配字符串的开头和结尾。这将使模式匹配整个字符串并产生您想要的结果:

string input = "Mountain View, CA 94043";
string pattern = @"^(?i:(?:([^\d,]+?)\W+\b((?:CA|SD|SC|CT|DC)\b)?\W*)?(\d{5}(?:[- ]\d{3,4})?)?)$";

Match m = Regex.Match(input, pattern);

foreach (Group g in m.Groups)
{
    Console.WriteLine(g.Value);
}

由于您没有将模式限制为完全匹配,如上所述,它发现了部分匹配,尤其是因为您的某些组是完全可选的。因此,它将“Mountain”视为匹配,然后将“View,CA 94043”视为下一场比赛。

编辑:根据评论中的要求,我将尝试指出Java和.NET正则表达式方法之间的差异。

在Java中,如果模式匹配整个字符串,matches()方法返回true / false。因此,它不需要使用边界锚或原子零宽度断言来修改模式。在.NET中,没有这样的等效方法可以为您完成此操作。相反,您需要显式添加^$元字符,以分别匹配字符串或行的开头和结尾,或\A\z元字符为整个字符串做同样的事情。有关.NET元字符的参考,请查看this MSDN page。我不确定Java matches()使用哪一组锚,尽管this article建议使用\A\z

Java的matches()返回一个布尔值,.NET提供Regex.IsMatch() method来做同样的事情(除了已经讨论过的匹配整个字符串的区别)。 Java find()方法的.NET等效项是Regex.Match() method,您可以在循环中使用它继续查找下一个匹配项。此外,.NET提供了一个Regex.Matches()方法,可以为您执行此操作,并返回成功匹配的集合。根据您的需要和输入,这可能没问题,但为了增加灵活性,您可能需要在循环中检查Match.Success并使用Match.NextMatch() method继续查找匹配项(此示例可在NextMatch链接)。