this regex crate生锈时我有点问题。我需要匹配所有的':word'字符串,但不需要匹配引号。
不幸的是,发现here之类的(?!\B"[^"]*)(:[a-zA-Z0-9]{1,})(?![^"]*"\B)
之类的某些方法不起作用,返回了look-around, including look-ahead and look-behind, is not supported
错误。
目前,我可以使用以下正则表达式来匹配所有':word'字符串:(:[a-zA-Z0-9]{1,})
let rparams = Regex::new(r#"(:[a-zA-Z0-9]{1,})"#).unwrap(); // doesn't work: match the ':20'
let raw_sql = "select * from aa where a = '10-10-10 20:20'; select * from aa where a = :num";
println!("{}", rparams.replace_all(raw_sql, "?").to_string());
// Returns: select * from aa where a = '10-10-10 20?'; select * from aa where a = ?
// Expected: select * from aa where a = '10-10-10 20:20'; select * from aa where a = ?
感谢您的帮助
答案 0 :(得分:2)
看看Regular expression: match word not between quotes中描述的解决方案,看来您可以通过匹配要替换的零件,而又匹配并捕获您想要的零件而无需环顾四周忽略(引号内的文本)。
必要的正则表达式只是('[^']*')|:\w+
-regex101 example
这将匹配+捕获包含任何其他字符的任何一对单引号,并匹配任何冒号:
后跟一个或多个单词字符。
然后使用replace_all
和replacer closure来检查捕获组:如果有捕获组,它将是匹配的引号,因此将其替换为它;如果没有捕获组,则为匹配关键字,因此将其替换为所需的值。
示例:
use regex::{Regex, Captures};
fn main() {
let rparams = Regex::new(r#"('[^']*')|:\w+"#).unwrap();
let raw_sql = "select * from aa where a = '10-10-10 20:20'; select * from aa where a = :num";
println!("{}", rparams.replace_all(raw_sql, |caps: &Captures| {
match caps.get(1) {
Some(same) => same.as_str().to_string(),
None => "?".to_string()
}
}).to_string());
}
[a-zA-Z0-9]
,但是\w
(与[a-zA-Z0-9_]
相同)似乎更合理,因为它允许使用:num_one
答案 1 :(得分:-2)
我认为您的问题超出了正则表达式的范围。我认为解决这个问题的最简单的方法是编写一个令牌生成器,以一次检查一个字符串中的所有令牌。