C# Regex从没有分区的长代码串中拆分不同的代码

C# Regex从没有分区的长代码串中拆分不同的代码,c#,regex,C#,Regex,我(基本上)有一个大约600000个代码的文件 它们看起来像这样: HJ43EKU2 BJX4700QHJ43EKU2KU89EJKM 当存储/加载它们时,它们看起来如下所示: HJ43EKU2 BJX4700QHJ43EKU2KU89EJKM 每个代码正好是8位数字 它们是字母数字(a-Z,0-9),没有重音或符号 所以这是可行的(用于拆分代码块): 但有一个问题,因为某些格式的代码不是像这样的有效代码: MF93276H 第7位数字不能是数字 这不会太糟糕,除非有一个例外,即如果代

我(基本上)有一个大约600000个代码的文件

它们看起来像这样:

HJ43EKU2
BJX4700QHJ43EKU2KU89EJKM
当存储/加载它们时,它们看起来如下所示:

HJ43EKU2
BJX4700QHJ43EKU2KU89EJKM
每个代码正好是8位数字

它们是字母数字(a-Z,0-9),没有重音或符号

所以这是可行的(用于拆分代码块):

但有一个问题,因为某些格式的代码不是像这样的有效代码:

MF93276H
第7位数字不能是数字

这不会太糟糕,除非有一个例外,即如果代码的第二位是
N
(或字母表中更高的数字),那么这将使代码再次有效

如何对正则表达式实现一些逻辑,以便它考虑到重新验证代码的规则的“例外情况”?

在C#中,您可以使用已知的技术使用捕获组,然后对其进行评估:

var rx = "[a-zA-Z0-9]N[a-zA-Z0-9]{4}[0-9][a-zA-Z0-9]|([a-zA-Z0-9]{6}[0-9][a-zA-Z0-9])|[a-zA-Z0-9]{6}[a-zA-Z][a-zA-Z0-9]";
var results = Regex.Matches("BJX4700QHJ43EKU2KU89EJKM", rx)
            .Cast<Match>()
            .Where(m => !m.Groups[1].Success)
            .Select(z => z.Value);
foreach (var s in results)
    Console.WriteLine(s);
var rx=“[a-zA-Z0-9]N[a-zA-Z0-9]{4}[0-9][a-zA-Z0-9]|([a-zA-Z0-9]{6}[0-9][a-zA-Z0-9])|[a-zA-Z0-9]{6}[a-zA-Z][a-zA Z0 9];
var结果=正则表达式匹配(“BJX4700QHJ43EKU289EJKM”,rx)
.Cast()
.Where(m=>!m.Groups[1]。成功)
.选择(z=>z.Value);
foreach(结果中的var s)
控制台。写入线(s);

正则表达式详细信息

  • [a-zA-Z0-9]N[a-zA-Z0-9]{4}[0-9][a-zA-Z0-9]
    -第二个字符等于的有效代码模式
  • |
    -或
  • ([a-zA-Z0-9]{6}[0-9][a-zA-Z0-9])
    -第1组(如果匹配,则丢弃):无效的代码模式
  • |
    -或
  • [a-zA-Z0-9]{6}[a-zA-Z][a-zA-Z0-9]
    -有效的代码模式
注意:如果N(或字母表中的更高版本)表示如果第二个字符是
O
p
Z
,您需要将第一个备选方案中的
N
替换为
[N-Z]

代码详细信息

  • 。其中(m=>!m.Groups[1].Success)
    -如果组1不匹配,则匹配的代码是有效代码,因此仅获取这些代码
  • .Select(z=>z.Value)
    -仅在结果中保留整个匹配对象值文本
    • 我强烈建议您不要这样做,但.NET实际上支持条件组,因此您可以:

      var pattern=“[a-zA-Z0-9](?:(?N)|[a-zA-Z0-9-[nN]])[a-zA-Z0-9]{4}(?(N)[a-zA-Z0-9]|[a-zA-Z])[a-zA-Z0-9]”;
      Regex.IsMatch(“MF93276H”)//false
      Regex.IsMatch(“MN93276H”)//true
      
      我会使用替代结构:

      var x = @"HJ43EKU2";
      var match =
          Regex.Match(x, @"(?i)[a-z0-9](?([n-z])[a-z0-9]{7}|[a-z0-9]{5}[a-z][a-z0-9])");
      var code = match.Value;
      
      (?i)
      使搜索不区分大小写

      (?(n-z))
      零宽度断言,用于检查第二个字符是
      n
      还是“更多”

      [a-z0-9]{7}
      如果第二个字符
      N
      或更多,则允许第七个字符为数字


      [a-z0-9]{5}[a-z][a-z0-9]
      如果第二个字符不是
      或更多,则不允许第七个字符是数字对于上面发布的
      BJX4700QHJ43EKU289EJKM
      的预期结果是什么?是否在PHP中?语言风格是什么?
      HJ43EKU2
      KU89EJKM
      @WiktorStribiżew C#顺便说一句,如果你想让你的正则表达式对象使用不区分大小写的匹配,你可以将
      [a-zA-Z0-9]
      减少到
      [a-Z0-9]
      ,在保持可读性的同时缩短你的正则表达式模式…@Sanguine实际上,要理解你问题中的逻辑有点困难,请注意我的笔记。我想你可以不用零宽度前瞻。只需使
      [n-z]
      匹配,然后是6
      [a-z0-9]
      。还是对regex模式的简单性投了赞成票……不,没有人投反对票。我只是不小心没有启动(再次单击了向上投票按钮,因为我紧张不安,没有注意)。我的坏毛病,现在就好了;-)