将两个正则表达式 A 和 B 组合成 C = (A and not B)

Combining two regular expressions A and B into C = (A and not B)

假设我有一个正则表达式 A 和另一个正则表达式 B 作为输入。我想创建一个新的正则表达式 C 匹配一行当且仅当

我可以为 AB 的非常简单的情况手动创建 C : 假设 AxBy,那么 C = ^[^y]*x[^y]*$ 将是一个有效的解决方案。

显然,随着 AB 变得更加复杂,问题变得更加困难。是否存在用于从 AB 中创建这样的正则表达式 C 的通用算法?


注:由于regular languages are closed under intersection and complement,理论上应该存在这样的算法。我知道现代 IT 系统中可用的正则表达式的表达能力超过了正式的正则语言,但是 AB 的解决方案是仅限于形式语言可用的功能子集,但 C 使用现代正则表达式引擎的扩展功能,对我来说非常好。

编辑

根据 OP 的初始正则表达式,正如 @ruakh 在我的回答下方的评论中指出的那样,OP 选择使用 ^(?!.*B).*A。此解决方案匹配 包含 B 的任何字符串,而不是我最初的 post(下方)目标,即 匹配的任何字符串 B 正如最初假设的那样,后来由 OP 澄清(在我的回答下方的评论中)。


原版Post

如果我对你的问题的理解正确,你正在寻找匹配一个字符串,该字符串匹配一个给定的模式 A,但不匹配模式 B,这样你的新模式 CAB.

组成

简单的正则表达式

鉴于模式 Ax 并且模式 By,新的正则表达式模式 C 应该如下:

^(?!B$)A$

或使用您提供的示例正则表达式:

^(?!y$)x$

也许下面是一个更好的例子来证明这一点:

  • A 模式:x.
  • B 模式:xx
  • C 变为:^(?!xx$)x.$

here

所示,这将匹配 xa 但不匹配 xx

复杂的正则表达式

关于更复杂的正则表达式,它可能完全取决于模式和所使用的正则表达式引擎。正则表达式可能会超时,如果使用递归、控制动词、模式修饰符等,它可能会完全崩溃。

更好的选择是使用代码独立评估两个正则表达式以确定结果。

示例 1

这是一个正则表达式中断的示例,因为两个模式都使用相同的预定义模式名称:

  • A: (?(DEFINE)(?<t>x))(?&t).
  • B: (?(DEFINE)(?<t>x))(?&t){2}
  • C: ^(?!(?(DEFINE)(?<t>x))(?&t){2}$)(?(DEFINE)(?<t>x))(?&t).$

如图所示失败here

示例 2

这是一个无法正常工作的递归示例:

  • A: a(?R)z
  • B: az
  • ^(?!az$)a(?R)?z$

如图所示失败here


当然,这假设初始假设 C: ^(?!B$)A$ 是用于匹配 A 和 non-matching 的正确模式 B.

我猜答案很可能是 因为 A、B 和 C 可以 依赖independent 表达式,那么结果将属于 combination 类别,其中还包括 permutation 实例,并且会有一个无数这样的表达。然后,我非常怀疑是否会有一种 通用算法