提问人:Mike Thompson 提问时间:8/25/2008 最后编辑:KevMike Thompson 更新时间:11/19/2011 访问量:7112
捕获重复组
Capturing a repeated group
问:
我正在尝试使用.NET正则表达式解析如下所示的字符串:
H3Y5NC8E-TGA5B6SB-2NVAQ4E0
并使用 Split 返回以下内容: H3Y5NC8E TGA5B6SB 2NVAQ4E0型
我根据特定的字符集验证每个字符(请注意,字母“I”、“O”、“U”和“W”不存在),因此使用字符串。拆分不是一种选择。每个组中的字符数可以不同,组数也可以不同。我使用以下表达式:
([ABCDEFGHJKLMNPQRSTVXYZ0123456789]{8}-?){3}
这将恰好匹配 3 组,每组 8 个字符。任何或多或少都会使比赛失败。 只要它与输入正确匹配,它就会起作用。但是,当我使用 Split 方法提取每个字符组时,我只得到最后一个组。RegexBuddy抱怨我重复了捕获组本身,我应该在重复组周围放置一个捕获组。然而,我这样做的尝试都没有达到预期的结果。我一直在尝试这样的表达方式:
(([ABCDEFGHJKLMNPQRSTVXYZ0123456789]{8})-?){4}
但这行不通。
由于我在代码中生成正则表达式,因此我可以将其扩展为组数,但我希望有一个更优雅的解决方案。
请注意,字符集不包括整个字母表。它是产品激活系统的一部分。因此,任何可能被意外解释为数字或其他字符的字符都将被删除。例如,字母“I”、“O”、“U”和“W”不在字符集中。
连字符是可选的,因为用户不需要在顶部输入它们,但如果用户完成复制和粘贴,它们就可以在那里。
答:
为什么要使用正则表达式?如果组总是用 - 分割,你不能使用 Split() 吗?
对不起,如果这不是您的意图,但您的字符串总是使用连字符分隔组,而不是使用正则表达式,您不能使用 String.Split() 方法吗?
Dim stringArray As Array = someString.Split("-")
您可以使用以下模式:
Regex.Split("H3Y5NC8E-TGA5B6SB-2NVAQ4E0", "([ABCDEFGHJKLMNPQRSTVXYZ0123456789]{8}+)-?")
但是您需要从生成的数组中过滤掉空字符串。 来自MSDN的引文:
如果多个匹配项彼此相邻,则在数组中插入一个空字符串。
有效区块的定义特征是什么?我们需要知道这一点才能真正提供帮助。
我的一般建议是,在第一步中验证字符集,然后根据你的期望在单独的方法中拆分和解析。如果这是在网站/应用程序中,则可以在前端使用 ASP 正则表达式验证,然后在后端将其分解。
在查看了您的问题和给出的答案后,我想出了这个:
RegexOptions options = RegexOptions.None;
Regex regex = new Regex(@"([ABCDEFGHJKLMNPQRSTVXYZ0123456789]{8})", options);
string input = @"H3Y5NC8E-TGA5B6SB-2NVAQ4E0";
MatchCollection matches = regex.Matches(input);
for (int i = 0; i != matches.Count; ++i)
{
string match = matches[i].Value;
}
由于“-”是可选的,因此不需要包含它。我不确定你最后用{4}做什么?这将根据您想要的内容找到匹配项,然后使用 MatchCollection 您可以访问每个匹配项以重新生成字符串。
如果你只是用 group(i).value 检查组的值,那么你只会得到最后一个。但是,如果要枚举捕获该组的所有时间,请使用 group(2).captures(i).value,如下所示。
system.text.RegularExpressions.Regex.Match("H3Y5NC8E-TGA5B6SB-2NVAQ4E0","(([ABCDEFGHJKLMNPQRSTVXYZ0123456789]+)-?)*").Groups(2).Captures(i).Value
话筒
您可以在字符组中使用您选择的字符集。您只需要添加“+”修饰符即可捕获所有组。请参阅我之前的答案,只需将 [A-Z0-9] 更改为您需要的任何内容(即 [ABCDEFGHJKLMNPQRSTVXYZ0123456789])
我找到了我所追求的答案。这是我的工作代码:
static void Main(string[] args)
{
string pattern = @"^\s*((?<group>[ABCDEFGHJKLMNPQRSTVXYZ0123456789]{8})-?){3}\s*$";
string input = "H3Y5NC8E-TGA5B6SB-2NVAQ4E0";
Regex re = new Regex(pattern);
Match m = re.Match(input);
if (m.Success)
foreach (Capture c in m.Groups["group"].Captures)
Console.WriteLine(c.Value);
}
顺便说一句,您可以将 [ABCDEFGHJKLMNPQRSTVXYZ0123456789] 字符类替换为可读性更强的减法字符类。
[[A-Z\d]-[IOUW]]
如果您只想匹配这样的 3 个组,为什么不在正则表达式中使用此模式 3 次,而只使用捕获的 1、2、3 个子组来形成新字符串呢?
([[A-Z\d]-[IOUW]]){8}-([[A-Z\d]-[IOUW]]){8}-([[A-Z\d]-[IOUW]]){8}
在PHP中,我会返回(我不知道.NET)
return "$1 $2 $3";
评论