Javascript -- 正则表达式 -- 以部分匹配结束的多个单词的黑名单

Javascript -- Regex -- Blacklist of multiple words to END with a partial match

我读过很多关于 Whosebug 的问题,包括 this one, this one, and even read Rexegg's Best Trick, which is also in a question here. I found this one,它适用于整行,但不是“一切都是坏话”。 None 其中对我有帮助,所以我开始:

Javascript 中,我有一个很长的正则表达式模式。我正在尝试匹配类似句子结构的序列,如下所示:

1 UniquePrefixA [some-token] and [some-token] want to take [some-token] to see some monkeys.

2 UniqueC [some-token] wants to take [some-token] to the store. UniqueB, [some-token] is in the pattern once more.

3 UniquePrefixA [some-token] is using [some-token] to [some-token].

请注意,每个模式都以唯一的前缀开头。遇到该前缀表示模式的开始。 如果我在捕获过程中再次遇到该模式,我不应该捕获第二次出现,然后停止。我会捕获该前缀之前的所有内容。

如果我在后面的模式中没有遇到前缀,我需要继续匹配那个模式。

我也在使用捕获组(不再重复,因为捕获组只有 return 该组的最后一个匹配项)。捕获组内容需要 returned,所以我使用匹配,非贪婪。

这是我的图案和 working example

/(?:UniquePrefixA|UniqueB|UniqueC)\s*(\[some-token\])(?:and|\s)*(\[some-token\])?(\s|[^\[\]])*(\[some-token\])? --->(\s|[^\[\]])*<--- (\[some-token\])?(\s|[^\[\]])*/i

它基本上是 2 个按特定顺序重复的模式:

(\s|[^\[\]])*     // Basicaly .*, but excluding brackets
(\[some-token\])  // A token [some-token]

如何防止匹配继续过去一个单词黑名单?

我希望这发生在我画了三个箭头的地方,以供参考。相当于 Any 字符,但不是此列表的内容:(UniquePrefixA|UniqueB|UniqueC)(如捕获组 1 中所示)。

我可能需要更好地了解负前瞻,或者它是否可以处理一组事物。 最重要的是,我想知道消极的前瞻性方法是否可以支持选项列表或者是否有更好的方法?如果答案是“你不能那样做,”这也很酷。

我认为,更易于维护的解决方案是将您的任务分为两部分:

  1. 查找每个 文本,从您的任何唯一前缀开始, 到下一个或字符串的末尾。

  2. 处理每个这样的块,寻找你的一些令牌,也许 还有他们之间的内容。

执行第一个任务的正则表达式应包括 3 个部分:

  • (?:UniquePrefixA|UniqueB|UniqueC) - 一个非捕获组寻找 对于任何唯一前缀。
  • ((?:.|\n)+?) - 捕获组 - 要进一步捕获的片段 处理(见下面的注释)。
  • (?=UniquePrefixA|UniqueB|UniqueC|$) - 积极向前看 对于任何唯一前缀或字符串结尾(停止条件 您正在寻找)。

总而言之,整个正则表达式如下所示:

/(?:UniquePrefixA|UniqueB|UniqueC)((?:.|\n)+?)(?=UniquePrefixA|UniqueB|UniqueC|$)/gi

注意:不幸的是,JavaScript正则表达式的风格没有实现 单行-s)选项。因此,捕获组中不只是 . 以上,必须使用(?:.|\n),意思是:

  • \n (.),
  • 以外的任何字符
  • \n.

这两种变体都"enveloped"进入非捕获组, 设置变体的限制(| 的两侧),因为重复 标记 (+?) 适用于两种变体。

?+之后,意思是勉强版本。

因此正则表达式的这一部分(捕获组)将匹配任何字符序列 包括 \n,在下一个uniqie前缀(如果有的话)之前结束, 正如你所料。

第二个任务是将另一个正则表达式应用于捕获的块(第 1 组), 寻找 [some-token]s 以及它们之间的内容。 你没有具体说明你想对每个块做什么, 所以我不确定第二个正则表达式应该包含什么。 也许只匹配 [some-token]?

就足够了

确保模式不会出现在重复字符序列中,例如 (\s|[^\[\]])*,请注意 \s 包含在 [^\[\]] 中,因此可能只是 [^\[\]]*,是在重复模式的左侧和内部添加一个否定前瞻(这是一个零长度匹配断言,如 ^),以便检查每个字符:

((?!UniquePrefixA)(\s|[^\[\]]))*