这里有一些简单的复制粘贴代码,它不仅仅适用于确切的单词异常。
复制/粘贴代码:
在以下正则表达式中,仅用您的正则表达式替换全部大写部分。
Python 正则表达式
pattern = r"REGEX_BEFORE(?>(?P<exceptions_group_1>EXCEPTION_PATTERN)|YOUR_NORMAL_PATTERN)(?(exceptions_group_1)always(?<=fail)|)REGEX_AFTER"
红宝石正则表达式
pattern = /REGEX_BEFORE(?>(?<exceptions_group_1>EXCEPTION_PATTERN)|YOUR_NORMAL_PATTERN)(?(<exceptions_group_1>)always(?<=fail)|)REGEX_AFTER/
PCRE正则表达式
REGEX_BEFORE(?>(?<exceptions_group_1>EXCEPTION_PATTERN)|YOUR_NORMAL_PATTERN)(?(exceptions_group_1)always(?<=fail)|)REGEX_AFTER
JavaScript
截至 2020 年 6 月 17 日,这是不可能的,而且在不久的将来可能也不可能。
完整示例
REGEX_BEFORE = \b
YOUR_NORMAL_PATTERN = \w+
REGEX_AFTER =
EXCEPTION_PATTERN = (苹果|橙子|果汁)
Python 正则表达式
pattern = r"\b(?>(?P<exceptions_group_1>(apple|orange|juice))|\w+)(?(exceptions_group_1)always(?<=fail)|)"
红宝石正则表达式
pattern = /\b(?>(?<exceptions_group_1>(apple|orange|juice))|\w+)(?(<exceptions_group_1>)always(?<=fail)|)/
PCRE正则表达式
\b(?>(?<exceptions_group_1>(apple|orange|juice))|\w+)(?(exceptions_group_1)always(?<=fail)|)
它是如何工作的?
这使用了相当复杂的正则表达式,即原子组、条件、Lookbehinds 和命名组。
这(?>
是一个原子组的开始,这意味着它不允许回溯:这意味着,如果该组匹配一次,但后来因为后向失败而失效,那么整个组将无法匹配。(在这种情况下我们想要这种行为)。
(?<exceptions_group_1>
创建一个命名的捕获组。它比使用数字更容易。请注意,该模式首先尝试查找异常,然后如果找不到异常,则回退到正常模式。
请注意,原子模式首先尝试查找异常,然后如果找不到异常则回退到正常模式。
真正的魔力在(?(exceptions_group_1)
. 这是一个询问 exceptions_group_1 是否成功匹配的条件。如果是,那么它会尝试查找always(?<=fail)
. 这种模式(正如它所说的)总是会失败,因为它会寻找“always”这个词,然后它会检查“does "ways"=="fail"',但它永远不会。
因为条件失败,这意味着原子组失败,并且因为它是原子的,这意味着它不允许回溯(试图寻找正常模式),因为它已经匹配了异常。
这绝对不是这些工具的预期用途,但它应该可靠且高效地工作。
Ruby中原始问题的确切答案
/\b(?>(?<exceptions_group_1>(apple|orange|juice))|\w+)(?(<exceptions_group_1>)always(?<=fail)|)/
与其他方法不同,可以修改此方法以拒绝任何模式,例如任何不包含子字符串“apple”、“orange”或“juice”的单词。
/\b(?>(?<exceptions_group_1>\w*(apple|orange|juice))|\w+)(?(<exceptions_group_1>)always(?<=fail)|)/