我需要将持续非单词与最后一个单词匹配到字符串(两个选项)。通过将其替换为null,将从原始字符串中删除匹配项。我目前的结果是:
正则表达式:
\W* # Matches optional lasts non-words.
\w* # Matches optional last word.
$
工作案例: unit tests here
String Removed Result
----------------------------------------------------------------------------
"Hello World!" "!" "Hello World"
"Hello World" " World" "Hello"
"Hello " " " "Hello"
"Hello" "Hello" ""
"Hello; World!" "!" "Hello; World"
"Hello; World" "; World" "Hello"
"Hello;" ";" "Hello"
当然,我遇到了问题。我希望接受HTML实体作为单词的一部分,但因为它有非单词字符(结尾分号),所以它最终分号匹配并被错误替换。
目前我预计只有匹配简单的HTML实体,基本上它是&\w+;
(如&aaccute;
),我稍后会对其进行改进(目前,让我们使用它来简化回答)。
我的期望: unit tests here, failing for now
String Removed Result
----------------------------------------------------------------------------
"Hell&aaccute; World!" "!" "Hell&aaccute; World"
"Hell&aaccute; World" " World" "Hell&aaccute;"
"Hell&aaccute;" "Hell&aaccute;" ""
"&aaccute; &aaccute;" " &aaccute;" "&aaccute;"
"&aaccute; " " " "&aaccute;"
"&aaccute;" "&aaccute;" ""
我想只需要在某个地方添加HTML实体表达式,以避免在第一个表达式(\W*
)上匹配它。但是我尝试了一些事情并没有用。
答案 0 :(得分:1)
我不知道如何明确说明完成正则表达式匹配目标的方法。我相信你需要一个可变宽度的负面回顾来避免匹配不需要的HTML实体,这在我见过的任何实现中都不存在。
但是,如果您的真正目标只是以您指定的方式分割字符串,则有两种方法可以实现该目标。
#1
您可以将初步字符作为一个组进行匹配和使用,仅使用第一个组匹配(${result}
)替换原始字符串。如您在问题中所述,${removed}
将使文本与删除的字符相匹配。
^(?<result>.*?(?:(?:&[a-z]+;)|\w)*?)(?<removed>(\W*)((?:&[a-z]+;|\w)*))(?<=.)$
@ regex101
由于所有匹配都是可选的,因此存在尾随(?<=.)
以避免匹配完全空行。我也正在使用您建议的HTML实体的简化定义(例如,假设小写并忽略数字实体,例如“&amp;#60;”)。
所有更新的单元测试都通过。
#2
或者,您可以反转字符串并使用类似此正则表达式的内容来匹配要删除的所需字符:
^(?<removed>((?:;[a-z]+&|\w)*)((?:[^\w;]|;(?![a-z]+&))*))(?<=.)
然后,删除字符后,重新反转字符串。 ${removed}
将删除已删除的字符(作为反向字符串)。请注意,到目前为止,我只对“反向”正则表达式进行了一些初步测试。
答案 1 :(得分:0)
您无法使用\w
,因为它不包含您指出的HTML实体。
相反,接受任何字母和 HTML实体的组合,如下所示:
([a-zA-Z]*(&[a-zA-Z]+;)*[a-zA-Z]*)+\s([a-zA-Z]*(&[a-zA-Z]+;)*[a-zA-Z]*)+$
https://regex101.com/r/pH7tK2/2