我需要创建一个单个正则表达式(使用.NET 3.5 Regex,如果这很重要),它允许以下三种可能性:
[A-Z]{2,3}
[A-Z]{2,3}-[A-Z][A-Z0-9]{1,2}
[A-Z]{2,3}-[A-Z][A-Z0-9]{1,2}-[A-Z0-9]{2,3}
因此BIG
,BIG-A9
或BIG-A09-SD
会匹配,
但BIG-F
,BIG-A9S-
或BIG-A09-S
不匹配。
我应该澄清一些事情:
我需要匹配整条线,而不仅仅是它的一部分。
我正在尝试为正在将此字符串键入TextBox
的用户提供反馈。因此,我正在寻找一个正则表达式,我可以用它来测试TextBox的内容,只要它发生变化。例如,当用户键入“A”时,反馈应为负数,因为它们尚未匹配案例1.一旦他们键入“AA”,反馈将为正,因为他们已匹配案例1.在键入“AAE”后,他们应该仍然得到积极的反馈,因为他们已经匹配案例1.如果他们输入“AA7”,反馈应该是负面的。如果他们继续输入并输入“AAE-”,则反馈应该再次为负,因为他们还没有遇到案例2,并且已超过案例1.
我把头发拉出来(剩下的是什么)。
那里有人知道如何以一种有效的方式表达这一点吗?
答案 0 :(得分:5)
您的正则表达式模式可以根据作为其他人前缀的属性进行排序。所以尝试嵌套的可选后缀:
(?:[A-Z]{2,3}(?:-[A-Z][A-Z0-9]{1,2}(?:-[A-Z0-9]{2,3})?)?)
答案 1 :(得分:3)
通常,正则表达式根据最左边最长的规则进行匹配,其正式表达式(来自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})
注意第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})?)?
你去吧。正则表达式引擎不需要回溯和最小前瞻。
已编辑注意从下面的O.P.评论中可以看出,所需的匹配是整个字符串。所以......
默认情况下,正则表达式会在源字符串中找到最左边的最长匹配项。如果要匹配整个字符串或整行,则需要使用元模式^
锚定表达式,其中将该位置的匹配锚定为起始线和$
,将该匹配锚定在该位置的行尾。所以......
^abc
,匹配前缀,匹配以abc
开头的所有字符串(abc
,abcabc
,abcc
,aabcdefg
等)。它与xyzabc
,ab
等<。p>
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
或SingleLine
编译正则表达式选项。 SingleLine
表示^
和$
仅在整个字符串的开头和结尾匹配,而.
匹配除\n
之外的任何字符。 MultiLine
表示^
和$
匹配字符串中任意一行的开头和结尾,.
匹配任何字符,包括 {{1 }}
如果要删除匹配的各种组件,可以在正则表达式中添加一些标记以创建命名组:
\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 ) ;
}
编译正则表达式可能会有很大帮助,尤其是当正则表达式变得复杂时。
如果你是正则表达式的新手(即使你不是!),你应该阅读Jeffrey Friedl最优秀的 opus ,Mastering Regular Expressions:< / p>
答案 2 :(得分:0)
为了满足我在键入输入时向用户提供持续反馈的要求,我将以下内容注册为Windows窗体的TextChanged事件处理程序。
private void TheTextChanged(object sender, EventArgs e)
{
var 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(textbox.Text);
if (m.Success)
{
string prefix = m.Groups["prefix"].Value;
string middle = m.Groups["middle"].Value;
string suffix = m.Groups["suffix"].Value;
if (prefix != "")
{
textbox.BackColor = prefix.Equals(textbox.Text) ? Color.LightGreen : Color.LightPink;
if (middle != "")
{
string twoparts = prefix + "-" + middle;
textbox.BackColor = twoparts.Equals(textbox.Text) ? Color.LightGreen : Color.LightPink;
if (suffix != "")
{
string threeparts = prefix + "-" + middle + "-" + suffix;
textbox.BackColor = threeparts.Equals(textbox.Text) ? Color.LightGreen : Color.LightPink;
}
}
}
}
else
{
textbox.BackColor = Color.LightPink;
}
}
这是一个WPF版本,只是因为。
private void TheTextChanged(object sender, TextChangedEventArgs e)
{
var 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(textbox.Text);
if (m.Success)
{
string prefix = m.Groups["prefix"].Value;
string middle = m.Groups["middle"].Value;
string suffix = m.Groups["suffix"].Value;
if (prefix != "")
{
textbox.Background = prefix.Equals(textbox.Text) ? Brushes.LightGreen : Brushes.LightPink;
if (middle != "")
{
string twoparts = prefix + "-" + middle;
textbox.Background = twoparts.Equals(textbox.Text) ? Brushes.LightGreen : Brushes.LightPink;
if (suffix != "")
{
string threeparts = prefix + "-" + middle + "-" + suffix;
textbox.Background = threeparts.Equals(textbox.Text) ? Brushes.LightGreen : Brushes.LightPink;
}
}
}
}
else
{
textbox.Background = Brushes.LightPink;
}
}
感谢所有的好答案!!我下次会尝试更加明确。