【问题标题】:Regex for anything but multicharacter token除多字符标记外的任何东西的正则表达式
【发布时间】:2016-01-09 22:04:12
【问题描述】:

我想创建一个正则表达式,它返回两个多字符标记之间的所有内容,其中开始标记为;;(,结束标记为;;),例如

;;(
  Capture this part, which can contain everything except the closing token 
;;)

我认为使用负前瞻的正则表达式/;;\((?!;;\));;\)/ 应该可以工作,但这不会返回任何匹配项。是否可以为此使用正则表达式?

【问题讨论】:

    标签: regex string regex-negation


    【解决方案1】:

    为了匹配两个多字符分隔符之间的某些文本,需要使用符合 unroll-the-loop 技术的正则表达式。

    所以,我们有 ;;(;;) 分隔符。

    惰性点匹配正则表达式是;;\((.*?);;\)。这种模式效率不高,因为当输入越来越大的文本时,它会变得越来越慢。

    ;;\(([^;]*(?:;(?!;\))[^;]*)*);;\) 一样展开它会使匹配线性化,如果块内有很多;,唯一的问题可能是速度问题。

    完成比赛需要 timgeb 的解法 169 步。我只需要 16 个步骤。

    另外,展开的正则表达式不依赖于/s DOTALL 修饰符,它可以省略。

    为什么不使用环视?当您需要重叠匹配或有特定条件时,环视非常有用。在这种情况下,您需要非重叠匹配,因为前导和尾随分隔符不相等使用捕获组,您需要获取的子模式周围的一对未转义括号。在;;\(([^;]*(?:;(?!;\))[^;]*)*);;\) 中,我们需要获取所有不是;;) 的文本,即这个[^;]*(?:;(?!;\))[^;]*)* 部分。因此,我们用() 括起来。

    这个展开的部分匹配什么?

    • [^;]* - 除了;(尾随分隔符的第一个字符)之外的任何内容
    • (?:;(?!;\))[^;]*)* - 零个或多个序列...
      • ;(?!;\)) - 尾随分隔符的第一个字符,文字 ;,后面没有 ;)(尾随分隔符的其余部分)
      • [^;]* - 除;(尾随分隔符的第一个字符)以外的零个或多个字符

    【讨论】:

      【解决方案2】:

      使用积极的后视和积极的前瞻。

      (?<=;;\().*?(?=;;\))
      

      演示:https://regex101.com/r/iK5wG4/2

      【讨论】:

      • 我不会在这里推荐任何前瞻。只需捕获您需要的内容,匹配分隔符但不要捕获它们。使用/;;\((.*?);;\)/ 并获取索引为 1 的值。环顾会涉及额外的开销。并非所有语言都支持它们。
      • @stribizhev 我喜欢先行/后行,因为当您想在较长的字符串中找到多个此类组时,这种方法不会中断。
      • 你可以对我的正则表达式版本做同样的事情。更有效,更快。我不会使用惰性点匹配,我会使用展开的点匹配。你的需要 169 步。我会使用需要 16 个步骤的;;\(([^;]*(?:;(?!;\))[^;]*)*);;\)。我想我需要发布那个。
      • @stribizhev 你是对的,它在这里工作是因为令牌不能重叠,因此你不会遇到消耗开始/结束令牌的问题。很好的观察!
      猜你喜欢
      • 2020-10-13
      • 1970-01-01
      • 1970-01-01
      • 2021-08-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-04
      相关资源
      最近更新 更多