如何将正则环视组合为逻辑组,实现帕斯卡命名特殊词不拆分
问题:处理帕斯卡命名拆分中的固定复合词
我原本用带正向后行断言和正向前行断言的正则表达式(?<=[a-z])(?=[A-Z])拆分帕斯卡命名的字符串,比如能把"MyPascalCasedString"拆成["My", "Pascal", "Cased", "String"]。现在需要处理特殊情况:像"LibreOffice"这种看起来是帕斯卡命名,但要当成单个词不拆分的固定组合。我试了加负环视写成(?<=[a-z])(?=[A-Z])(?<!Libre)(?!Office),虽然能把"ThisIsLibreOffice"拆成["This", "Is", "LibreOffice"],但会误判其他情况——比如"ThisIsLibreSoftware"会被拆成["This", "Is", "LibreSoftware"],"ThisIsAnotherOffice"会被拆成["This", "Is", "AnotherOffice"],这两个其实应该拆分才对。请问怎么组合负环视,让它只在"Libre"后面跟"Office"的时候才不拆分,同时保留原来两个正环视的功能?
解决方案
核心是要让负环视同时匹配前后的特定组合,而不是单独排除"Libre"结尾或"Office"开头的位置。你需要把两个负环视合并成一个逻辑:当当前位置的前几个字符是"Libre",且后几个字符是"Office"的时候,才不进行拆分;其他符合小写接大写的位置都正常拆分。
正确的正则表达式
(?<=[a-z])(?=[A-Z])(?<!Libre(?=[A-Z]Office))
逻辑解释
- 保留原有的
(?<=[a-z])(?=[A-Z]):确保只在小写字母后面紧跟大写字母的位置拆分。 - 新增的
(?<!Libre(?=[A-Z]Office))是嵌套了正向前瞻的负后行断言:- 先检查当前位置的前面是否是"Libre",同时这个"Libre"后面紧跟的是大写O开头的"Office"(也就是
LibreOffice这个固定组合的分界处)。 - 只有当这个嵌套条件满足时,才排除该位置的拆分;其他所有小写接大写的位置,都正常执行拆分。
- 先检查当前位置的前面是否是"Libre",同时这个"Libre"后面紧跟的是大写O开头的"Office"(也就是
测试效果
- 对"ThisIsLibreOffice":
Libre后面的O开头Office被匹配,该位置不拆分,结果为["This", "Is", "LibreOffice"] - 对"ThisIsLibreSoftware":
Libre后面是S开头的Software,不满足嵌套条件,Libre和Software之间会拆分,结果为["This", "Is", "Libre", "Software"] - 对"ThisIsAnotherOffice":
Another和Office之间的位置前面不是Libre,正常拆分,结果为["This", "Is", "Another", "Office"]
扩展:添加更多固定复合词
如果后续需要处理类似的其他固定组合(比如"OpenOffice"),可以用|分隔多个规则扩展正则:
(?<=[a-z])(?=[A-Z])(?<!(Libre(?=[A-Z]Office)|Open(?=[A-Z]Office)))
内容的提问来源于stack exchange,提问作者Dominik
相关产品推荐
相关产品推荐

