如何编写自己的函数来匹配字符串模式?

How can I write my own function for matching string patterns?

我正在尝试 replace String 中的所有非字母数字字符与 _。到目前为止,我已经想出了相反的方法:

fn main() {
    let a = String::from("hello!");
    println!("{}", sanitize(a)); // prints "_____!"
}


fn sanitize(check: String) -> String {
    check.replace(char::is_alphanumeric, "_")
}

当我尝试反转 check.replace 行上的 Pattern 时,出现错误:

fn main() {
    let a = String::from("hello!");
    println!("{}", sanitize(a)); // should print "hello_"
}


fn sanitize(check: String) -> String {
    check.replace(!char::is_alphanumeric, "_")
}
error[E0600]: cannot apply unary operator `!` to type `fn(char) -> bool {char::methods::<impl char>::is_alphanumeric}`
   --> src/main.rs:146:19
    |
146 |     check.replace(!char::is_alphanumeric, "_")
    |                   ^^^^^^^^^^^^^^^^^^^^^^ cannot apply unary operator `!`

反转此 Pattern 的语法是什么,以便我可以替换非字母数字字符?

我在 matches 的文档中注意到 char::is_alphanumeric 是有效的 Pattern,因为它是“确定字符是否匹配的函数或闭包”。我想如果需要我可以编写自己的函数,但是对于应该如何编写该函数有限制吗?

似乎可以在任何需要 Pattern 的地方使用自定义函数,只要它以 char 作为唯一参数,并且 returns 和 bool. Doc:

impl<'a, F> Pattern<'a> for F where
    F: FnMut(char) -> bool, 

在我的例子中,我得到了以下结果:

fn main() {
    let a = String::from("hello!");
    println!("{}", sanitize(a)); // should print "hello_"
}


fn sanitize(check: String) -> String {
    check.replace(evil_chars, "_")
}

fn evil_chars(c: char) -> bool {
    !char::is_alphanumeric(c)
}

惯用的方法是使用闭包(除非您确实需要在多个地方使用的单独函数)。正如您在文档中所见,模式可以是与签名 FnMut(char) -> bool 匹配的“函数或闭包”。使用简单地否定 char::is_alphanumeric 的闭包看起来像这样:

fn sanitize(check: String) -> String {
    check.replace(|c| !char::is_alphanumeric(c), "_")
}