使用 nom 将任何空格、制表符、换行符等序列替换为单个空格

问题描述 投票:0回答:1

我现在正在学习用

nom
进行解析,出现了一些我无法自己解决的问题。有一个我想在这里问一下。 首先:我不确定我是否真的需要使用
nom
来实现此目的,但这似乎是检测空格、制表符、换行符和回车符的任何组合的最简单方法。我想用一个空格替换这些字符的任何序列。我的那种不优雅的解决方案看起来像这样:

enum EmptyOrStr {
    Empty,
    Str(char),

fn replace_multispaces<'a>(i: &str) -> IResult<&str, String> {
    let (rest, tokens) = many0(alt((
        map(multispace1, |_| EmptyOrStr::Empty),
        // i would like to use `not(multispace1)` instead of `anychar`,
        // but then the output type is `()` and I cannot put it into the 
        // `EmptyOrStr::Str( )`-variant
        map(anychar, |s| EmptyOrStr::Str(s)),
    )))(i)?;

    Ok((
        "",
        tokens
            .into_iter()
            .map(|t| match t {
                EmptyOrStr::Str(s) => format!("{s}"), // because s is a `char` not a `&str`
                EmptyOrStr::Empty => " ".to_string(),
            })
            .collect::<String>(),
    ))
}

我没能用 &str 做到这一点。直觉上我猜想让

alt
内部的第二个解析器使用类似
take_till1(is_multispace1)
之类的东西会更好,但这需要一个条件,而不是解析器。 我认为有太多的东西一起使用,我无法理解所有内容。

理想情况下,用单个空格替换

multispace
不需要 nom。但我认为 multispace1 函数非常实用。

有什么明显的方法可以改进这个吗?

string rust replace nom alt-attribute
1个回答
0
投票

如果您只想将输入分割为任意数量的连续空白字符,则可以使用

split_ascii_whitspace()

下面的示例函数使用

split_ascii_whitespace()
来分割输入并使用单个空格字符重新连接它。

fn strip_multispace(input: &str) -> String {
    input.split_ascii_whitespace().collect::<Vec<&str>>().join(" ")
}

fn main() {
    let s = "This is    a string with\t multiple\n\r\n white\t\t\r\nspaces";
    println!("{}", strip_multispace(s));
}

输出:

This is a string with multiple white spaces
© www.soinside.com 2019 - 2024. All rights reserved.