正则表达式问题

古斯凡

我需要创建一个单个正则表达式(使用.NET 3.5正则表达式,如果有的话),它允许以下三种可能性:

  1. [A-Z]{2,3}
  2. [A-Z]{2,3}-[A-Z][A-Z0-9]{1,2}
  3. [A-Z]{2,3}-[A-Z][A-Z0-9]{1,2}-[A-Z0-9]{2,3}

因此BIGBIG-A9BIG-A09-SD将匹配,但是BIG-FBIG-A9S-BIG-A09-S将不匹配。

我应该澄清一些事情:

  • 我需要匹配整条线,而不仅仅是部分。

  • 我正在尝试为正在将此字符串键入的过程中的用户提供反馈TextBox因此,我正在寻找一个正则表达式,每当它更改时,我都可以使用该正则表达式来测试TextBox的内容。例如,当用户键入“ A”时,反馈应该为负,因为他们尚未匹配案例1。一旦键入“ AA”,则反馈将为正,因为他们已经匹配案例1。键入“ AAE”后,他们由于它们与案例1相匹配,因此仍应收到正反馈。如果键入“ AA7”,则反馈应为负。如果他们然后继续输入并输入“ AAE-”,则由于他们还没有满足情况2并超过情况1,因此反馈应该再次变为否定。

我正在拔头发(还剩多少)。

外面有人知道如何以一种可行的方式表达这一点吗?

尼古拉斯·凯里(Nicholas Carey)

通常,正则表达式将根据最左边最长的规则进行匹配,该规则的正式表达式(根据Posix标准)为:

进行搜索,就好像测试了字符串的所有可能后缀中是否存在与模式匹配的前缀一样。选择包含匹配前缀的最长后缀,并将所选后缀的最长可能匹配前缀标识为匹配序列。

您的三种可能性中的每一种都是前一种的扩展。从您的第三个和最长的开始:

[A-Z]{2,3}-[A-Z][A-Z0-9]{1,2}-[A-Z0-9]{2,3}

它包含3个组件,每个组件本身就是一个正则表达式:

  • [A-Z]{2,3}
  • -[A-Z][A-Z0-9]{1,2}
  • -[A-Z0-9]{2,3}

首先,您需要对它们进行分组

  • ([A-Z]{2,3})
  • (-[A-Z][A-Z0-9]{1,2})
  • (-[A-Z0-9]{2,3})

然后,可以将最后两个合并为更长的正则表达式

  • ([A-Z]{2,3})
  • (-[A-Z][A-Z0-9]{1,2})(-[A-Z0-9]{2,3})

请注意,如果有第二个分段,则第三个分段是可选的,因此请使用后缀运算符'?' 使它如此:

  • ([A-Z]{2,3})
  • (-[A-Z][A-Z0-9]{1,2})(-[A-Z0-9]{2,3})?

现在将整个第二个组件分组,以表明它是一个整体:

  • ([A-Z]{2,3})
  • ((-[A-Z][A-Z0-9]{1,2})(-[A-Z0-9]{2,3})?)

请注意,如果我们拥有第一个组件,那么整个第二个组件都是可选的,因此再次使用后缀运算符?来表示可选性:

  • ([A-Z]{2,3})
  • ((-[A-Z][A-Z0-9]{1,2})(-[A-Z0-9]{2,3})?)?

最后,将两个正则表达式连接起来以形成最终表达式:

([A-Z]{2,3})((-[A-Z][A-Z0-9]{1,2})(-[A-Z0-9]{2,3})?)?

妳去 正则表达式引擎无需回溯,并且前瞻性极低。

编辑注释从以下OP的注释中看来,所需的匹配项是整个字符串所以...

默认情况下,正则表达式在源字符串中找到最左边最长的匹配项。如果你想匹配整个字符串整条生产线,需要与元模式,表达^,匹配在那个位置开始,其中锚系法和$,其中位置是结束线锚比赛。所以...

  • ^abc,匹配的前缀,任何字符串起始具有匹配abcabcabcabcabccaabcdefg,等等)。它不匹配之类的东西xyzabcab等等。

  • abc$类似地,匹配的后缀时,匹配任何行结束abcabcxyzabc等)。它不匹配之类的东西abxyzababcxyz,等。

  • ^abc$匹配字符串abc,没有别的。

要匹配整行,请使用上面的正则表达式并放下锚点:

^([A-Z]{2,3})((-[A-Z][A-Z0-9]{1,2})(-[A-Z0-9]{2,3})?)?$

这里的所有都是它的。应该注意,然而,该行为.^$取决于是否正则表达式将与编译MultilineSingleLine选项。SingleLine表示^$仅在整个字符串的开头和末尾.匹配,并且与以外的任何字符匹配\nMultiLine表示^$匹配在字符串中任何行的开头和结尾,并.匹配包括在内的 任何字符\n

如果您想找出匹配的各种组件,则可以在正则表达式中添加一些标记来创建命名组

(?<prefix>[A-Z]{2,3})((-(?<middle>[A-Z][A-Z0-9]{1,2}))(-(?<suffix>[A-Z0-9]{2,3}))?)?

通过该名称,您可以按名称访问匹配的组,从而使代码更具可读性:

Regex rx = new Regex( @"(?<prefix>[A-Z]{2,3})((-(?<middle>[A-Z][A-Z0-9]{1,2}))(-(?<suffix>[A-Z0-9]{2,3}))?)?" , RegexOptions.ExplicitCapture );
Match m = rx.Match(s) ;

if ( m.Success )
{
  string prefix = m.Groups["prefix"].Value ;
  string middle = m.Groups["middle"].Value ;
  string suffix = m.Groups["suffix"].Value ;

  Console.WriteLine( "prefix: {0}" , prefix ) ;
  Console.WriteLine( "middle: {0}" , middle ) ;
  Console.WriteLine( "suffix: {0}", suffix  ) ;

}

性能提示:使用命名组并使用编译正则表达式RegexOptions.ExplicitCapture可能会有很大帮助,尤其是当您的正则表达式变得复杂时。

如果您不熟悉正则表达式(即使您不是!),则应阅读Jeffrey Friedl最出色的作品掌握正则表达式》

掌握正则表达式

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章