如何使用 Rust 正则表达式分割字符串并保留分隔符?

15

我有一个由分隔符分开的字符串。我想用正则表达式拆分此字符串并保留分隔符。

我的目前代码是:

use regex::Regex; // 1.1.8

fn main() {
    let seperator = Regex::new(r"([ ,.]+)").expect("Invalid regex");
    let splits: Vec<_> = seperator.split("this... is a, test").into_iter().collect();
    for split in splits {
        println!("\"{}\"", split);
    }
}

其输出为:

"this"
"is"
"a"
"test"
我希望保留分隔符(在这种情况下是空格字符),我希望看到的输出是:
"this"
"... "
"is"
" "
"a"
", "
"test"

如果可能的话,我该如何使用 regex 实现这种行为?

这与 保留分隔符来拆分字符串 不同,后者使用标准库而不是 regex 库。


1
为什么你想保留它们,你知道它们只是空格。 - Stargateur
1
空格只是一个示例。我实际上将匹配其他字符/序列。我会编辑问题以澄清。 - Ian Rehwinkel
3
由于复制品未使用“regex”包,因此它并不是完全匹配的。我认为在这种情况下,您最好使用find_iter()方法来查找所有分隔符及其起始和结束索引,或者扩展正则表达式以 匹配分隔符或分隔符之间的文本 。 (我会将此作为答案添加,但它并不适合重复,因此我将其保留为评论。) - Sven Marnach
1
@SvenMarnach 在将来,随时欢迎您编辑问题,使其成为一个明确清晰的重复。如果我关闭/编辑了问题,您也可以直接 @-提及我。它现在已经重新打开了。 - Shepmaster
1个回答

10

根据Regex类型的文档记录:

使用 Regexstd::str::pattern 方法

注意:本节需要在编译此包时启用 pattern Cargo 特性,这需要 Rust Nightly 版本。

由于Regex实现了Pattern接口,因此您可以使用在&str上定义的方法来使用正则表达式。例如,is_matchfindfind_itersplit可以替换为str::containsstr::findstr::match_indicesstr::split

通过使用pattern特性,您可以使用分割字符串并保留分隔符的技巧中所述的技术:

use regex::Regex; // 1.1.8

fn split_keep<'a>(r: &Regex, text: &'a str) -> Vec<&'a str> {
    let mut result = Vec::new();
    let mut last = 0;
    for (index, matched) in text.match_indices(r) {
        if last != index {
            result.push(&text[last..index]);
        }
        result.push(matched);
        last = index + matched.len();
    }
    if last < text.len() {
        result.push(&text[last..]);
    }
    result
}

fn main() {
    let seperator = Regex::new(r"([ ,.]+)").expect("Invalid regex");
    let splits = split_keep(&seperator, "this... is a, test");
    for split in splits {
        println!("\"{}\"", split);
    }
}

这也给你提供了一个提示,如何转换代码以不需要夜间版Rust:

例如,[...] find_iter [...] 可以替换为 [...] str::match_indices

使用反向转换来使用稳定的Regex方法。


1
我在 Rust 1.42.0-nightly 和 1.40 中遇到了错误 error[E0277]: expected a std::ops::Fn<(char,)> closure, found regex::re_unicode::Regex,出现在 split_keeptext.match_indices(r) 处。 - stuart
1
@stuart,请确认您是否遵循了答案顶部关于启用“pattern”功能的多个警告。 - Shepmaster
啊,尽管触发了大量的VSCode警告,但它在Cargo.toml中与以下内容一起工作:regex = { version = "1.1.8", features = ["pattern"] } - stuart

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接