3

我正在尝试使用 .NET 正则表达式解析如下字符串:

H3Y5NC8E-TGA5B6SB-2NVAQ4E0

并使用拆分返回以下内容:H3Y5NC8E TGA5B6SB 2NVAQ4E0

我根据特定字符集验证每个字符(请注意,不存在字母“I”、“O”、“U”和“W”),因此不能使用 string.Split。每个组中的字符数可以变化,组数也可以变化。我正在使用以下表达式:

([ABCDEFGHJKLMNPQRSTVXYZ0123456789]{8}-?){3}

这将完全匹配 3 组,每组 8 个字符。或多或少都会导致比赛失败。只要它正确匹配输入,它就可以工作。但是,当我使用 Split 方法提取每个字符组时,我只得到最后一个组。RegexBuddy 抱怨我已经重复了捕获组本身,并且我应该在重复组周围放置一个捕获组。但是,我的任何尝试都没有达到预期的结果。我一直在尝试这样的表达:

(([ABCDEFGHJKLMNPQRSTVXYZ0123456789]{8})-?){4}

但这不起作用。

由于我在代码中生成了正则表达式,我可以将其扩展为组数,但我希望有一个更优雅的解决方案。


请注意,字符集不包括整个字母表。它是产品激活系统的一部分。因此,任何可能被意外解释为数字或其他字符的字符都将被删除。例如,字母“I”、“O”、“U”和“W”不在字符集中。

连字符是可选的,因为用户不需要在顶部键入它们,但如果用户完成复制和粘贴,它们可以在那里。

4

9 回答 9

5

顺便说一句,您可以用更具可读性的减法字符类替换 [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";
于 2008-08-25T12:01:15.183 回答
3

在查看了您的问题和给出的答案后,我想出了这个:

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 您可以访问每个匹配项以重建字符串。

于 2008-08-25T02:53:26.793 回答
3

我发现了我想要的答案。这是我的工作代码:

    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);
    }
于 2008-08-25T03:33:47.303 回答
0

为什么使用正则表达式?如果组总是被-分割,你不能使用Split()吗?

于 2008-08-25T02:06:33.740 回答
0

抱歉,如果这不是您想要的,但是您的字符串总是有分隔组的连字符,那么您不能使用 String.Split() 方法而不是使用正则表达式吗?

Dim stringArray As Array = someString.Split("-")
于 2008-08-25T02:09:28.053 回答
0

您可以使用此模式:

Regex.Split("H3Y5NC8E-TGA5B6SB-2NVAQ4E0", "([ABCDEFGHJKLMNPQRSTVXYZ0123456789]{8}+)-?")

但是您需要从结果数组中过滤掉空字符串。来自MSDN的引用:

如果多个匹配项彼此相邻,则将一个空字符串插入到数组中。

于 2008-08-25T02:44:24.567 回答
0

有效区块的定义特征是什么?我们需要知道这一点才能真正提供帮助。

我的一般建议是,在第一步中验证字符集,然后根据您的期望以单独的方法拆分和解析。如果这是在网站/应用程序中,那么您可以在前端使用 ASP 正则表达式验证,然后在后端将其分解。

于 2008-08-25T02:51:18.920 回答
0

如果您只是使用 group(i).value 检查组的值,那么您只会得到最后一个。但是,如果要枚举该组被捕获的所有时间,请使用 group(2).captures(i).value,如下所示。

system.text.RegularExpressions.Regex.Match("H3Y5NC8E-TGA5B6SB-2NVAQ4E0","(([ABCDEFGHJKLMNPQRSTVXYZ0123456789]+)-?)*").Groups(2).Captures(i).Value
于 2008-08-25T02:57:23.727 回答
0

麦克风,

您可以在字符组中使用您选择的字符集。您只需要添加“+”修饰符来捕获所有组。请参阅我以前的答案,只需将 [A-Z0-9] 更改为您需要的任何内容(即 [ABCDEFGHJKLMNPQRSTVXYZ0123456789])

于 2008-08-25T02:57:40.480 回答