RegEx - OR 值在捕获组更改结果中的顺序

RegEx - Order of OR'd values in capture group changes results

Visual Studio/XPath/RegEx:

给出的表达式:

(?<TheObject>(Car|Car Blue)) +(?<OldState>.+) +---> +(?<NewState>.+)

给定的搜索字符串:

Car Blue Flying ---> Crashed

我预计:

TheObject = "Car Blue"
OldState = "Flying"
NewState = "Crashed"

我得到的:

TheObject = "Car"
OldState = "Blue Flying"
NewState = "Crashed"

给定新的正则表达式:

(?<TheObject>(Car Blue|Car)) +(?<OldState>.+) +---> +(?<NewState>.+)

结果是(我想要的):

TheObject = "Car Blue"
OldState = "Flying"
NewState = "Crashed"

我从概念上了解引擎盖下发生的事情; RegEx 将它在 OR 列表中找到的第一个(从左到右)匹配放入 <TheObject> 组,然后继续。

OR 列表是在 运行 时构建的,无法保证 "Car" 或 "Car Blue" 添加到 <TheObject> 中的 OR 列表的顺序团体。 (这是大大简化的 OR 列表)

我可以通过将 OR 列表从最长到最短排序来暴力破解它,但是,我一直在寻找更优雅的东西。

有没有办法让 <TheObject> 组捕获它在 OR 列表中可以找到的最大的而不是它找到的第一个? (不用我担心顺序)

谢谢,

正则表达式的|运算符通常在底层使用Aho–Corasick算法。它总是会停在它找到的最左边的匹配项上。我们无法更改 | 运算符的行为。 所以解决方案是避免使用 | 运算符。使用 (Car( Blue)?).

而不是 (Car Blue|Car)(Car|Car Blue)
(?<TheObject>(Car( Blue)?) +(?<OldState>.+) +---> +(?<NewState>.+)

那么 <TheObject> 组在 Blue 的情况下将永远是 Car Blue

我通常会自动同意像 ltux 这样的答案,但在这种情况下不会。

你说交替组是动态生成的。它多久动态生成一次?如果这是每个用户请求,那么对构建表达式的对象进行快速排序(先按最长长度排序,或按字母顺序排序)可能比编写将 (Car|Car Red|Car Blue) 变成 [=11= 的东西更快].

正则表达式可能需要更长的时间(您甚至可能不会注意到正则表达式速度的差异)但汇编操作可能会快得多(取决于您的数据源的体系结构)交替列表)。

在 702 个选项的简单测试中,在三种方法中,使用这样的选项集的结果是可比较的,但是这些结果中的 none 正在计算构建字符串的时间,随着字符串复杂性的增加而增加。

选项都是一样的,只是格式不同

  • 快点
    • 击杀
    • 施乐
    • ...
    • 苹果
  • 是的
    • 击杀
    • 施乐
    • ...
    • 苹果
  • 施乐
    • 击杀
    • 施乐
    • ...
    • 苹果
  • ...
  • 苹果
    • 击杀
    • 施乐
    • ...
    • 苹果

使用 Google Chrome 和 Javascript,我尝试了 三种 (编辑:四种)不同的格式,并看到了所有格式之间的一致结果0-2ms.

  • 'Optimized factoring'a(?:4|3|2|1)?
  • Reverse alphabetically sorting (?:a4|a3|a2|a1|a)
  • Factoringa(?:4)?|a(?:3)?|a(?:2)?|a(?:1)?。所有都始终以 0 到 2 毫秒的速度进入(我想不同之处在于我的机器此刻可能正在做的其他事情)。
  • 更新: 我找到了一种无需在正则表达式中排序即可执行此操作的方法,使用前瞻 like this (?=a|a1|a2|a3|a4|a5)(.{15}|.(14}|.{13}|...|.{2}|.) 其中 15是上限一直向下计数到下限。
    • 如果对这种方法没有任何限制,我觉得它会导致很多问题和误报。这将是我最不喜欢的结果。如果前瞻匹配,捕获组 (.{15}|...) 将在任何情况下捕获比您希望的更多的捕获。换句话说,它将超越比赛。

尽管与我的因式分解示例相比,我编造了术语优化因式分解,但出于任何原因我不能推荐我的因式分解示例语法。排序将是最合乎逻辑的,而且 read/maintain 比利用前瞻更容易。

您没有深入了解您的数据,但如果子选​​项可以包含空格并且可能重叠,您可能仍需要对子组或因子进行进一步排序,从而进一步降低 "Optimized Factoring" 的值.

编辑: 明确地说,我提供了一个彻底的检查,说明为什么没有任何形式的因式分解在这里是有益的。至少我看不到任何方式。一个简单的 Array.Sort().Reverse().Join("|") 就给出了任何人在这种情况下所需要的。