【问题标题】:RegEx matching with no single letter delimiter没有单个字母分隔符的正则表达式匹配
【发布时间】:2008-12-16 17:21:08
【问题描述】:

Medicare Eligibility EDI Example Responses 是我想要匹配的。

我有一个如下所示的字符串:

 LN:SMITHbbbbbbbbFN:SAMANTHAbbBD:19400515PD:1BN:123456PN:9876543210GP:ABCDEFGHIJKLMNOID:123456789012345bbbbbPC:123PH:8005551212CD:123456PB:123ED:20060101TD:2070101LC:NFI:12345678FE:20070101FT:20080101  PRE>

我需要一组如下所示的匹配项:

钥匙 |价值 ------------------ LN | SMITHbbbbbbbb FN |萨曼莎 BD | 19400515 ... 等等

我整天都在处理这个问题,但我似乎无法获得可接受的匹配方案。如果我想不通,我将使用 for 循环对其进行程序化编程并查找冒号索引。

我尝试过使用negative lookahead,但我无处可去。这是 C#,我在测试时使用 this tester (.Net) 以及 The Regex Coach (非 .Net)。

我试过用这个:

([\w]{2})\:(?![\w]{2}\:)

但这仅匹配键及其冒号,例如“LN:”、“FN:”等。

如果我使用:

([\w]{2})\:(.+?)([\w]{2})\:

它也消耗下一个匹配的两个字符键和冒号,导致我只匹配每个其他键/值对。

有没有办法让我在 .Net 中使用 RegEx 正确匹配这些,还是我坚持使用更程序化的解决方案?请记住,我不能假设键总是大写字母。它们可能包含数字,但它们始终是两个字符,然后是一个冒号。

提前感谢您提供的任何帮助。

【问题讨论】:

    标签: c# regex lookahead negative-lookahead


    【解决方案1】:

    我认为你想要的是积极的前瞻,而不是消极的,这样你就可以在当前位置之前找到键冒号组合,但你不会消耗它。这似乎适用于您的测试示例:

    ([\w]{2})\:(.+?)(?=[\w]{2}\:|$)
    

    产量:

    LN: SMITHbbbbbbbb FN:萨曼莎布 BD: 19400515 PD:1 国行号:123456 电话:9876543210 ...

    注意:我在测试输出中添加了冒号,它们没有被正则表达式捕获。

    编辑:谢谢,Douglas,我已经编辑了正则表达式以捕获字符串结尾,因此最后一个条目也被捕获。

    【讨论】:

    • 我们可能需要一些东西来匹配最终条目?
    • 对。我已将其添加到我的。我试图让它与命名组一起工作,然后我会将它标记为已回答。 :)
    • 好酷,(?[\w]{2})\:(?.+?)(?=([\w]{2}\:|$ )) 在显式捕获模式下给了我我想要的东西。谢谢亚当!
    【解决方案2】:

    这在 JavaScript 中有效(我总是在 Firefox 中启动错误控制台以使用正则表达式),但它在 .NET 中也应该可以正常工作:

    ([^:]{2}):((?:[^:](?!(?:[^:]:)))+)

    它使用负前瞻:

    ( -> 开始捕获第一个标记(标签) [^:]{2} -> 两个非冒号字符 ) -> 结束捕获第一个令牌 : -> 跳过冒号 ( -> 开始捕获第二个标记(值) (?: -> 不要将此组捕获为令牌 [^:](?! -> 一个非冒号字符,后面不跟: (?: -> 不要捕获这个组 [^:]: -> 一个非冒号,后跟一个冒号 ) -> 结束组 ) -> 结束负前瞻 )+ -> 该组中的一个或多个 ) -> 结束捕获第二个标记

    测试:

    "LN:SMITHbbbbbbbbFN:SAMANTHAbbBD:19400515"
        .replace(
            /([^:]{2}):((?:[^:](?!(?:[^:]:)))+)/g,
            "[$1] = [$2]\n")
    

    产量:

    [LN] = [SMITHbbbbbbbb] [FN] = [SAMANTHAbb] [BD] = [19400515]

    【讨论】:

      【解决方案3】:

      查看链接,每个字段的长度都是固定的,因此您可以执行以下操作:

      int pos = 0;
      Dictionary<string, string> parsedResults = new Dictionary<string, string>();
      
      foreach (int length in new int[] { 13, 10, 8, 1, 6, 10, 15, 20, 3, 10, 6, 3, 8, 8, 1, 8, 8, 8, })
      {
          string fieldId = message.Substring(pos, 2);
          string fieldValue = message.Substring(pos + 3, length);
          parsedResults.Add(fieldId, fieldValue);
          pos += length + 3;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-10-13
        • 2011-08-29
        • 1970-01-01
        • 1970-01-01
        • 2013-08-11
        • 1970-01-01
        • 2013-06-03
        相关资源
        最近更新 更多