【问题标题】:Regex match comma not inside quotes in rust正则表达式匹配逗号不在 rust 引号内
【发布时间】:2020-10-07 02:55:23
【问题描述】:

this regex crate 生锈了。我需要匹配所有 ':word' 字符串,但不在引号内。

不幸的是,像 (?!\B"[^"]*)(:[a-zA-Z0-9]{1,})(?![^"]*"\B) 这样的一些方法,发现 here,不起作用,返回 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

感谢您的帮助

【问题讨论】:

  • 不是 Rust,而是相关的:Regular expression: match word not between quotes
  • 有什么问题?如果您有一个有效的正则表达式,那有什么问题?如果您拥有的正则表达式不起作用,它有什么问题?
  • @trentcl 问题中描述了问题:环视正则表达式不起作用,因为regex 不支持环视。他尝试了另一个正则表达式,但它匹配 所有内容 而不仅仅是引号之外的内容(请参阅“返回”与“预期”cmets)

标签: regex rust


【解决方案1】:

查看Regular expression: match word not between quotes 中描述的解决方案,您似乎可以通过匹配您想要替换的部分,同时匹配并捕获您想要忽略的部分,无需环顾四周(引号内的文字)。

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

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

然后您使用replacer closure 和replace_all 来检查捕获组:如果有捕获组,它将是匹配的引用,因此将其替换为自身;如果没有捕获组,则为匹配的关键字,因此将其替换为所需的值。

例子:

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. 如果引号中有转义的引号,这将不起作用(但可以使用链接问题中看到的更复杂的正则表达式来实现)

【讨论】:

  • 很好的答案。需要注意的是,在regex crate 中,\w 支持 Unicode,因此比[a-zA-Z0-9_] 大很多。因此,如果您真的只想坚持使用 ASCII,最好将其写出来或使用 [[:word:]] 或 (?-u:\w),它们始终只是 ASCII 并且始终等同于 [a-zA-Z0-9_]。
【解决方案2】:

我认为您的问题超出了正则表达式的能力。我认为最简单的处理方法是编写一个标记器来按顺序检查字符串中的所有标记,一次一个。

【讨论】:

    猜你喜欢
    • 2020-05-21
    • 1970-01-01
    • 2021-07-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-01
    相关资源
    最近更新 更多