PCRE REGEX 匹配包含一组字符的一个或多个句子

PCRE REGEX to match one or more sentences containing a set of characters

我的文本块只包含 一个 特定的 HTML 标签(即“标记”标签),我想从所有连续的标签中提取一段包含该标签的“句子”。我用例中的“句子”由问号、感叹号、句号或分号分隔。

编辑:“mark”标签是在服务器端自动生成的,它们总是格式正确的。在我的用例中没有召唤克苏鲁的风险。

我试过的:

this PCRE regex, which works for selecting all sentences that contain the word "flung", see for example this regex tester 中的第二个结果开始。我添加了分号,因为它们也在我的用例中:

/[^.;?!]*(?<=[.;?\s!])flung(?=[\s.;?!])[^.;?!]*[.;?!]/igm

这很好用,除了两个我仍然需要帮助的问题:

我的期望:

例1:(基本匹配)

harum quidem rerum facilis est et expedita distinctio? Nam libero tempore, cum soluta nobis est eligendi optio <mark>cumque</mark> nihil impedit .23 quo minus id 0.89 quod maxime placeat facere possimus, omnis voluptas assumenda est, 12.34 omnis dolor repellendus! Itaque earum rerum hic tenetur a sapiente delectus, quod maxime placeat

应该return

Nam libero tempore, cum soluta nobis est eligendi optio <mark>cumque</mark> nihil impedit .23 quo minus id 0.89 quod maxime placeat facere possimus, omnis voluptas assumenda est, 12.34 omnis dolor repellendus!

因为那是包含“mark”标签的句子,小数点不是句号

示例 2(任何不包含标记 但介于 其他标记句子之间的句子也将包括在内。)

At vero eos et accusamus et iusto odio dignissimos ducimus. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do <mark>eiusmod</mark> tempor incididunt ut labore et dolore <mark>magna</mark> aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea <mark>commodo</mark> consequat? Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur! Excepteur sint <mark>occaecat</mark> cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum; sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam?

应该 return 下面(请注意句子“Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur!”是如何包含的,即使它没有标签,因为它介于另外两个匹配的句子)。

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do <mark>eiusmod</mark> tempor incididunt ut labore et dolore <mark>magna</mark> aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea <mark>commodo</mark> consequat? Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur! Excepteur sint <mark>occaecat</mark> cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum

您可以使用符合您要求的 PCRE 正则表达式:

((?<!\S)[^.?!;]*?<mark>.+?(?>[.?;!](?!\S)|\z))(?>(?>\h+.+?[.;?!])*?\h+(?1))*

RegEx Demo

正则表达式详细信息:

  • (?<!\S) 断言我们在当前位置之前没有空格
  • [^.?!;]*?:匹配0个或多个未在[...]
  • 中列出的任何字符
  • (?:\h+.+?[.?!;])*: 在标记的句子之间匹配0个或多个句子
  • (?>[.?;!](?!\S)|\z):断言我们在匹配句子终止符或匹配输入结束后当前位置后没有空格
  • (?1) 递归第一个子模式

其他策略:由于同一段落中两个带有<mark>的句子之间的句子必须包含在结果中,您可以贪婪地匹配所有开始标签和结束标签之间没有的内容包含换行符(即在同一段落中)。

~
(?<!\S)
(?> [^.?!;<]* (?:\.(?=\S))? )+
<mark> .* </mark>
.*? [.?;!]
(?!\S)
~ix

demo

或同优化:

~
(?<!\S)
(?> [^.?!;<]* (?:\.(?=\S))? )+
(*SKIP)
<mark> (?> [^\n<]* < )+ /mark>
(?> [^.?;!]* [.?;!] )+?
(?!\S)
~ix

demo

注意:这个问题也可以在没有正则表达式的情况下解决,使用 intlBreakIterator.