给出一个配置文件,该文件指定多个(可能是几十个)正则表达式,例如:
("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);
}
}
这需要Cargo.toml中的regex = "1"
,希望在当前目录中有一个名为config.conf
的配置文件,并且可以通过stdin操纵数据-Cargo.toml可以很好地用于测试目的。 / p>
RegexSet
并没有给我捕获信息,因此我用它可以有效地确定我是否完全匹配,然后再次匹配 进行替换。这让我感到不胜枚举,但这是我完全可以使用它的唯一方法。
第二,替换始终替换整个匹配项,而不仅仅是捕获的部分。这是我不了解的内容,不适合正则表达式的文档。
第三,遍历捕获-这可能是#2的原因-总是给我整个索引0的匹配,我想跳过它。在Rust中是否有类似“迭代此内容,但跳过第一个元素”的内容?