通常,正则表达式根据最左边最长的规则匹配,其形式表达式(来自 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 评论来看,所需的匹配似乎是整个 string。所以...
默认情况下,正则表达式在源字符串中查找最左边的最长匹配项。如果要匹配整个字符串或整行,则需要使用元模式锚定表达式,^
,它将该位置的匹配锚定到行首和$
,将匹配锚定在该位置的行尾. 所以...
^abc
abc
, 匹配前缀,匹配任何以( abc
, abcabc
, abcc
, aabcdefg
, 等)开头的字符串。xyzabc
它与,ab
等内容不匹配。
abc$
类似地,匹配一个后缀,匹配任何以abc
( abc
,xyzabc
等) 结尾的行。ab
它与, xyzab
,abcxyz
等内容不匹配。
^abc$
只会匹配字符串而不abc
匹配其他内容。
要匹配整行,请使用上述正则表达式并放置锚点:
^([A-Z]{2,3})((-[A-Z][A-Z0-9]{1,2})(-[A-Z0-9]{2,3})?)?$
这里的所有都是它的。然而,应该注意的是.
,^
和的行为$
取决于 或 正则表达式是否使用Multiline
orSingleLine
选项编译。SingleLine
表示^
and$
仅匹配整个字符串的开头和结尾,并且.
匹配除 . 之外的任何字符\n
。MultiLine
表示^
and$
匹配字符串中任何行的开头和结尾,并.
匹配任何字符,包括 \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最优秀的作品,掌握正则表达式: