捕获重复的组
我正在尝试使用.NET正则表达式解析如下字符串:
H3Y5NC8E-TGA5B6SB-2NVAQ4E0
并使用Split返回以下内容:
H3Y5NC8E
TGA5B6SB
2NVAQ4E0
我针对特定字符集验证每个字符(请注意,不存在字母" I"," O"," U"和" W"),因此不能使用string.Split。每个组中的字符数可以变化,并且组数也可以变化。我正在使用以下表达式:
([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的引用:
If multiple matches are adjacent to one another, an empty string is inserted into the array.
回答
有效块的定义特征是什么?我们需要知道这一点才能真正有所帮助。
我的一般建议是,首先验证字符集,然后根据期望使用单独的方法进行拆分和解析。如果位于网站/应用程序中,则可以在前端使用ASP Regex验证,然后在后端将其拆分。
回答
在审查了问题和给出的答案后,我想到了:
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]更改为所需的内容即可(即[ABCDEFGHJKLMNPNPSQRSTVXYZ0123456789])
回答
我已经找到了我想要的答案。这是我的工作代码:
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 " ";