【问题标题】:Regular expression that starts and ends with same string in special condition在特殊条件下以相同字符串开头和结尾的正则表达式
【发布时间】:2017-06-16 08:57:44
【问题描述】:

我需要一种机制来查找字符串中的数字,该数字要么被非数字字符包围,要么被字符串的开头/结尾或特殊分隔符(在本例中为 43)包围。以下是一些示例:

  • 订单号 12345678
  • 12345678
  • 12345678blabla
  • 431234567843

所有这些都应该匹配12345678。目前我正在使用以下正则表达式:

(?<=^|\D|43)([0-9]{8})(?=$|\D|43)

这个表达式效果很好,但有一个缺陷。如果数字以 43 开头但不以 43 结尾,我也会得到肯定的结果。以下是我得到那些“错误”结果的示例:

  • 4312345678
  • 4312345678blabla

我现在需要的是一个正则表达式的构造,以了解匹配的字符串是否以 43 开头,然后仅在它也以 43 结尾时才将其作为肯定结果返回。

【问题讨论】:

    标签: regex


    【解决方案1】:

    您可以在后视中使用积极的前瞻检查:

    (?<=^|\D|43(?=[0-9]{8}43))[0-9]{8}(?=43|\D|$)
               ^^^^^^^^^^^^^^
    

    请参阅regex demo

    现在,只有当43 之前并且 在 8 个随机数字之后,才会发生匹配。

    详情

    • (?&lt;=^|\D|43(?=[0-9]{8}43)) - 匹配字符串中立即出现的位置 前面有
      • ^ - 字符串开头
      • \D - 非数字符号
      • 43(?=[0-9]{8}43) - 43 后跟任意 8 位数字的子字符串,然后是 43 子字符串
    • [0-9]{8} - 正好 8 位
    • (?=43|\D|$) - 8 位数字后面必须跟:
      • 43 - 43 数字序列
      • \D - (=[^0-9]) 任何非数字符号
      • $ - 字符串结束。

    这是我自己的基于 conditional 的正则表达式,用于同一任务(可用于 .NET、PCRE,但不能用于 Java):

    (?<=^|[^0-9]|(43))[0-9]{8}(?=(?(1)43|(?:[^0-9]|$)))
    

    这是一个RegexStorm demo,在测试 .NET 正则表达式时很有用。

    Conditional construct的一些背景信息:

    此语言元素尝试匹配两种模式之一,具体取决于它是否可以匹配初始模式。它的语法是:

    (?( expression ) yes | no )

    其中 expression 是要匹配的初始模式,yes 是如果 expression 匹配则要匹配的模式,no 是如果 expression 不匹配则要匹配的可选模式。正则表达式引擎将表达式视为零宽度断言;也就是说,正则表达式引擎在计算表达式后不会在输入流中前进。

    因此,后视中的(43)捕获 到组 1 中,然后在条件内部,(?(1)43|(?:[^0-9]|$))(?(1)) 检查组 1 是否完全匹配,如果是, 43 被匹配,否则,(?:[^0-9]|$) 被尝试(任何非数字或字符串结尾。

    【讨论】:

      【解决方案2】:

      您可以使用conditional

      (?<=^|\D|(43))[0-9]{8}(?(1)(?=43)|(?=$|\D))
      

      第一个43在组1中被捕获,然后条件查询组1是否匹配任何东西。


      如果你的正则表达式引擎不支持条件,你可以试试这个“让你自己的条件”解决方法:

      (?<=^|\D|()43)[0-9]{8}(?=(?:\1(?:43)|(?!\1)(?:\D|$)))
      

      这个想法是用这样的替换替换条件(text)(?(1)a|b)()text(?:\1a|(?!\1)b)

      【讨论】:

      • 仅供参考:Java 正则表达式引擎不支持条件(请参阅demo)。我认为基于前瞻的解决方案更具跨平台兼容性。实际上,我首先用条件编写了正则表达式,并将其包含在我自己的答案中,但您将其发布为另一个答案。
      • @WiktorStribiżew 我不知道。添加了解决方法。
      猜你喜欢
      • 2017-09-17
      • 2013-08-04
      • 2023-01-02
      • 2015-04-27
      • 1970-01-01
      • 2016-12-07
      • 1970-01-01
      • 1970-01-01
      • 2018-03-19
      相关资源
      最近更新 更多