正则表达式匹配逗号不在rust内的引号内

时间:2020-10-07 02:55:23

标签: regex rust

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 = ?

This code running

感谢您的帮助

2 个答案:

答案 0 :(得分:2)

看看Regular expression: match word not between quotes中描述的解决方案,看来您可以通过匹配要替换的零件,而又匹配并捕获您想要的零件而无需环顾四周忽略(引号内的文本)。

必要的正则表达式只是('[^']*')|:\w+-regex101 example

这将匹配+捕获包含任何其他字符的任何一对单引号,并匹配任何冒号:后跟一个或多个单词字符。

然后使用replace_allreplacer 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());
}

Playground Link

注意:

  1. 您在示例中使用了[a-zA-Z0-9],但是\w(与[a-zA-Z0-9_]相同)似乎更合理,因为它允许使用:num_one
  2. 仅当字符串中的引号是平衡的时,这才有效
  3. 如果引号中包含转义的引号,则将无法正常工作(但可以使用链接问题中显示的更复杂的正则表达式来做到这一点)

答案 1 :(得分:-2)

我认为您的问题超出了正则表达式的范围。我认为解决这个问题的最简单的方法是编写一个令牌生成器,以一次检查一个字符串中的所有令牌。

相关问题