Rust Regex无环视时,如何匹配单括号而非双括号内的单词?
解决Rust Regex无法匹配连续
{...}结构的问题 这个问题我之前也碰到过,你的正则核心问题在于消耗了{前面的字符,导致连续的{these}{also}这类结构中,第二个{...}无法被捕获。原正则里的(?:[^{]|^)会吃掉{前面的非{字符(比如空格、前一个}),当匹配完{these}后,指针已经移到下一个{的位置,没有剩余字符能满足[^{]的匹配条件,自然就抓不到also了。
下面给你两个靠谱的解决方案:
方案1:先匹配所有{...},再用代码过滤转义项
既然Rust Regex不支持环视,我们可以换个思路:先把所有{...}结构都匹配出来,再通过代码判断哪些是需要保留的(排除被{{包裹的转义项)。这种方法不依赖正则的高级特性,兼容性更好。
extern crate regex; use regex::Regex; fn main() { // 匹配所有{...}结构,捕获内部的内容 let exp = Regex::new(r"\{([^{}]*)\}").unwrap(); let text = "{this} is a match, {{escaped}} is not, but {these}{also} are."; for capture in exp.captures_iter(text) { // 获取整个匹配项的起始位置,用来检查前一个字符 let match_start = capture.get(0).unwrap().start(); // 如果前一个字符是'{',说明这是转义的{{...}}里的内容,跳过 if match_start > 0 && text.as_bytes()[match_start - 1] == b'{' { continue; } // 输出我们需要的捕获内容 println!("{}", &capture[1]); } // 输出结果:this, these, also }
方案2:用新版Regex的有限环视功能(推荐)
如果你能把项目里的regex crate升级到1.0及以上版本,其实它支持固定长度的负后向环视(单个字符的环视是支持的)。这时候我们可以直接用正则来过滤转义项,不需要额外的代码判断:
extern crate regex; use regex::Regex; fn main() { // (?<!\{) 负后向环视:确保{前面不是{ // ([^{}]*) 捕获内部非{}的内容 // (?!\}) 负前向环视:确保}后面不是}(可选,根据你的转义规则调整) let exp = Regex::new(r"(?<!\{)\{([^{}]*)\}(?!\})").unwrap(); let text = "{this} is a match, {{escaped}} is not, but {these}{also} are."; for capture in exp.captures_iter(text) { println!("{}", &capture[1]); } // 输出结果:this, these, also }
这个正则里的(?<!\{)是零宽度的负后向环视,它不会消耗任何字符,只是检查{前面是不是{,这样连续的{...}{...}就能被依次匹配到,完美解决你的问题。
内容的提问来源于stack exchange,提问作者Boiethios
相关产品推荐
相关产品推荐

