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)
- Factoring
a(?: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("|")
就给出了任何人在这种情况下所需要的。
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)
- Factoring
a(?: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("|")
就给出了任何人在这种情况下所需要的。