正则如何实现两个分组互斥,仅匹配前缀或后缀其中之一的场景
正则前缀后缀互斥匹配解决方案
问题原因
你原来的正则将前缀、后缀分组都设为可选状态,未做互斥限制,因此会匹配到既没有前缀也没有后缀的普通字符串,出现误匹配。
修正后正则
如果你的正则引擎支持(?|分支重置语法,可以用下面的版本,匹配结果统一在捕获组1中:
(?i)(?|(?:NS)?Localized(?:App)?String(?:\(@|\.localizedString\(")([^"]+)|"(?!.*(?:NS)?Localized)([^"]+)"\.localized)
如果不支持分支重置语法,可以用下面的版本,匹配后取组1或组2中非空的结果即可:
(?i)(?:(?:NS)?Localized(?:App)?String(?:\(@|\.localizedString\(")([^"]+)|"(?!.*(?:NS)?Localized)([^"]+)"\.localized)
实现逻辑
通过「互斥分支」实现恰好满足一个条件的需求,将规则拆为两个独立分支,用|分隔:
- 第一个分支匹配带指定前缀、不带后缀的场景:匹配
NSLocalizedString、NSLocalizedAppString、localizedString三类前缀调用,捕获引号内的字符串内容 - 第二个分支匹配不带指定前缀、带后缀的场景:通过负向预查
(?!.*(?:NS)?Localized)排除带前缀的情况,仅匹配后缀为.localized的字符串,捕获引号内的内容
两个分支完全独立,不会出现「同时满足两个条件」或者「都不满足」的场景被匹配的问题。
测试用例验证
对给出的测试用例匹配结果如下:
print("Error: should NOT capture!"):无匹配,符合预期NSLocalizedAppString(@"Contextual Menu",nil)];:捕获内容为Contextual Menu,符合预期self.setTitleStates(["Unmute1".localized, "Mute".localized]):分别捕获Unmute1、Mute,符合预期NSApplication.localizedString("Paused", comment: ""):捕获内容为Paused,符合预期print("Remove from Set".localized):捕获内容为Remove from Set,符合预期
内容的提问来源于stack exchange,提问作者DarkByte
相关产品推荐
相关产品推荐

