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
这很好用,除了两个我仍然需要帮助的问题:
如何排除小数,例如12.34 比赛期间? “Lorem ipsum 12.34 dolor flung sit amet”应该是一句话。目前,它将十进制数字中的句点作为标点符号,但事实并非如此。我想修改 REGEX 以检测小数点周围是否有数字或字母会起作用,但我尝试了一个前瞻约束,例如 ?:[^\.]|\.(?=\d)
但它不匹配,或者我不匹配做对了。
我想修改它以匹配所有“标记”HTML标签而不是诸如“之类的词扔。我知道 REGEX 不适用于 html 标记,但是 HTML 解析器也无法识别这些字符(?!。;)。也许我可以考虑两者结合?
我的期望:
例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))*
正则表达式详细信息:
(?<!\S)
断言我们在当前位置之前没有空格
[^.?!;]*?
:匹配0个或多个未在[...]
中列出的任何字符
(?:\h+.+?[.?!;])*
: 在标记的句子之间匹配0个或多个句子
(?>[.?;!](?!\S)|\z)
:断言我们在匹配句子终止符或匹配输入结束后当前位置后没有空格
(?1)
递归第一个子模式
其他策略:由于同一段落中两个带有<mark>
的句子之间的句子必须包含在结果中,您可以贪婪地匹配所有开始标签和结束标签之间没有的内容包含换行符(即在同一段落中)。
~
(?<!\S)
(?> [^.?!;<]* (?:\.(?=\S))? )+
<mark> .* </mark>
.*? [.?;!]
(?!\S)
~ix
或同优化:
~
(?<!\S)
(?> [^.?!;<]* (?:\.(?=\S))? )+
(*SKIP)
<mark> (?> [^\n<]* < )+ /mark>
(?> [^.?;!]* [.?;!] )+?
(?!\S)
~ix
注意:这个问题也可以在没有正则表达式的情况下解决,使用 intlBreakIterator.
我的文本块只包含 一个 特定的 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
这很好用,除了两个我仍然需要帮助的问题:
如何排除小数,例如12.34 比赛期间? “Lorem ipsum 12.34 dolor flung sit amet”应该是一句话。目前,它将十进制数字中的句点作为标点符号,但事实并非如此。我想修改 REGEX 以检测小数点周围是否有数字或字母会起作用,但我尝试了一个前瞻约束,例如
?:[^\.]|\.(?=\d)
但它不匹配,或者我不匹配做对了。我想修改它以匹配所有“标记”HTML标签而不是诸如“之类的词扔。我知道 REGEX 不适用于 html 标记,但是 HTML 解析器也无法识别这些字符(?!。;)。也许我可以考虑两者结合?
我的期望:
例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))*
正则表达式详细信息:
(?<!\S)
断言我们在当前位置之前没有空格[^.?!;]*?
:匹配0个或多个未在[...]
中列出的任何字符
(?:\h+.+?[.?!;])*
: 在标记的句子之间匹配0个或多个句子(?>[.?;!](?!\S)|\z)
:断言我们在匹配句子终止符或匹配输入结束后当前位置后没有空格(?1)
递归第一个子模式
其他策略:由于同一段落中两个带有<mark>
的句子之间的句子必须包含在结果中,您可以贪婪地匹配所有开始标签和结束标签之间没有的内容包含换行符(即在同一段落中)。
~
(?<!\S)
(?> [^.?!;<]* (?:\.(?=\S))? )+
<mark> .* </mark>
.*? [.?;!]
(?!\S)
~ix
或同优化:
~
(?<!\S)
(?> [^.?!;<]* (?:\.(?=\S))? )+
(*SKIP)
<mark> (?> [^\n<]* < )+ /mark>
(?> [^.?;!]* [.?;!] )+?
(?!\S)
~ix
注意:这个问题也可以在没有正则表达式的情况下解决,使用 intlBreakIterator.