如何使用RegexSet进行替换?

时间:2019-05-22 15:45:48

标签: regex rust

给出一个配置文件,该文件指定多个(可能是几十个)正则表达式,例如:

("2018")
authors[ ]*=[ ]*(.*)

我想逐行遍历输入流并替换所有捕获(在此示例中,所有“ 2018”实例和作者姓名)。替换取决于捕获,因此年份将用“(year)”替换,作者名称用“(author)”替换。

我尝试过的

extern crate regex; // 1.1.5

use regex::Regex;
use regex::RegexSet;
use std::process;
use std::{
    fs::File,
    io,
    io::{prelude::*, BufReader},
    path::PathBuf,
};

fn main() {
    let contents = read_to_array("config.conf");
    println!("{:?}", contents);

    let set = RegexSet::new(&contents).unwrap(); // FIXME: this panics if there is an invalid regex
    println!("{:?}", set);

    let mut regexs: Vec<Regex> = Vec::new();
    for line in contents {
        let re = Regex::new(&line).unwrap(); // should not panic because we parsed Regexes above already
        regexs.push(re);
    }

    read(set, regexs);
}

fn read_to_array(filename: &str) -> Vec<String> {
    let file = File::open(filename).expect("no such file");
    let buf = BufReader::new(file);
    buf.lines()
        .map(|l| l.expect("Could not parse line"))
        .collect()
}

fn read(set: RegexSet, regexs: Vec<Regex>) {
    let stdin = io::stdin();
    for line in stdin.lock().lines() {
        let l = line.unwrap();
        let mut r = l.to_string();
        println!("line: {}", l);
        for idx in set.matches(&l).into_iter() {
            println!(
                "matches: {:?} - {:?} = {:?}",
                idx,
                set.patterns()[idx],
                regexs[idx]
            );
            for caps in regexs[idx].captures_iter(&l) {
                println!("captures: {:?}", caps);
                for c in caps.iter() {
                    println!("cap: {:?}", c);
                }
                r = regexs[idx].replace_all(&r, "xxx").to_string();
                println!("result: {:?}", r);
            }
        }
        println!("new line: {}", r);
    }
}

playground

这需要Cargo.toml中的regex = "1",希望在当前目录中有一个名为config.conf的配置文件,并且可以通过stdin操纵数据-Cargo.toml可以很好地用于测试目的。 / p>

什么不起作用

RegexSet并没有给我捕获信息,因此我用它可以有效地确定我是否完全匹配,然后再次匹配 进行替换。这让我感到不胜枚举,但这是我完全可以使用它的唯一方法。

第二,替换始终替换整个匹配项,而不仅仅是捕获的部分。这是我不了解的内容,不适合正则表达式的文档。

第三,遍历捕获-这可能是#2的原因-总是给我整个索引0的匹配,我想跳过它。在Rust中是否有类似“迭代此内容,但跳过第一个元素”的内容?

0 个答案:

没有答案