gpt4 book ai didi

java - 组合 (OR) 任意正则表达式

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:22:11 26 4
gpt4 key购买 nike

tl;dr 有没有办法在 Java 中将任意正则表达式或/组合成一个正则表达式(用于匹配,而不是捕获)?


在我的应用程序中,我收到了来自用户的两个列表:

  1. 正则表达式列表
  2. 字符串列表

我需要输出 (2) 中与 (1) 中的任何正则表达式都不匹配的字符串列表。

我有一个明显的简单实现(遍历 (2) 中的所有字符串;对于每个字符串遍历 (1) 中的所有模式;如果没有模式匹配该字符串,则将其添加到将返回的列表中)但是我想知道是否可以将所有模式组合成一个模式并让正则表达式编译器利用优化机会。

OR 组合正则表达式的明显方法显然是 (regex1)|(regex2)|(regex3)|...|(regexN) 但我很确定这不是正确的考虑到我无法控制各个正则表达式(例如,它们可能包含所有方式的后退/前向引用)。因此,我想知道您是否可以建议一种在 Java 中组合任意正则表达式的更好方法。


注意:上面仅暗示了这一点,但我会明确说明:我只匹配字符串 - 我不需要使用捕获组的输出。

最佳答案

一些正则表达式引擎(例如 PCRE)具有结构 (?|...) .它就像一个非捕获组,但具有一个很好的特性,即在每个交替组中都从相同的初始值开始计数。这可能会立即解决您的问题。因此,如果您可以选择为此任务切换语言,那应该可以解决问题。

[编辑:事实上,它仍然会导致冲突命名捕获组的问题。事实上,该模式甚至无法编译,因为组名无法重用。]

否则您将不得不操纵输入模式。 hyde 建议对反向引用重新编号,但我认为有一个更简单的选择:将所有组命名为组。您可以向自己保证这些名称是唯一的。

基本上,对于每个输入模式,您都会创建一个唯一标识符(例如,增加一个 ID)。然后最棘手的部分是在模式中找到捕获组。您将无法使用正则表达式执行此操作。您将不得不自己解析模式。如果您只是简单地遍历模式字符串,这里有一些关于需要注意什么的想法:

  • 输入和离开字符类时请注意,因为字符类内的括号是文字字符。
  • 也许是最棘手的部分:忽略所有后跟 ?: 的左括号, ?= , ?! , ?<= , ?<! , ?> .另外还有选项设置括号:(?idmsuxU-idmsuxU)(?idmsux-idmsux:somePatternHere)它也没有捕获任何内容(当然可以有这些选项的任何子集,它们可以按任何顺序排列 - - 也是可选的)。
  • 现在您应该只剩下左括号,它们是普通捕获组或命名组:(?<name> .最简单的方法可能是对它们一视同仁——也就是说,同时拥有一个数字和一个名称(如果未设置名称,则名称等于数字)。然后你用类似 (?<uniqueIdentifier-md5hashOfName> 的东西重写所有这些(连字符实际上不能是名称的一部分,您只会在递增的数字后跟散列 - 因为散列的长度是固定的,所以不会有任何重复;至少差不多)。请务必记住该组最初的编号和名称。
  • 每当遇到反斜杠时,有以下三种选择:
    1. 下一个字符是一个数字。你有一个编号的反向引用。将所有这些数字替换为 k<name>其中 name是您为群组生成的新群组名称。
    2. 接下来的字符是k<...> .再次将其替换为相应的新名称。
    3. 下一个字符是任何其他字符。跳过它。它同时处理括号的转义和反斜杠的转义。
  • 我认为 Java 可能允许前向引用。在那种情况下,您需要两次通过。首先注意重命名所有组。然后更改所有引用。

一旦你对每个输入模式都完成了这个,你就可以安全地将它们与 | 组合起来。 .反向引用以外的任何其他功能都不应该导致此方法出现问题。至少只要您的模式有效就不会。当然,如果你有输入a(bc)d那你就有问题了。但是,如果您不检查模式是否可以自行编译,您将始终拥有它。

我希望这能为您指明正确的方向。

关于java - 组合 (OR) 任意正则表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13890416/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com