如何在Rust中的两个模式之间获取子字符串?

时间:2016-06-13 07:25:51

标签: string rust

我想在Rust中创建一个子字符串。它以字符串的出现开始,以字符串末尾减去四个字符或某个字符结束。

我的第一个方法是

string[string.find("pattern").unwrap()..string.len()-5]

这是错误的,因为Rust的字符串是有效的UTF-8,因此是字节而不是基于字符的。

我的第二种方法是正确的但是过于冗长:

   let start_bytes = string.find("pattern").unwrap();
   let mut char_byte_counter = 0;
   let result = line.chars()
    .skip_while(|c| {
        char_byte_counter += c.len_utf8();
        return start_bytes > char_byte_counter;
    })
    .take_while(|c| *c != '<')
    .collect::<String>();

是否有更简单的方法来创建子串?我找不到标准库的任何部分吗?

1 个答案:

答案 0 :(得分:8)

我不记得其他语言中的内置库函数是否按照您想要的方式工作(给我两个模式之间的子串,如果第二个不存在,则在第一个和最后一个之间)。 我想你无论如何都要编写一些自定义逻辑。

相当于“substring”函数的关闭是切片。然而(正如你所发现的)它适用于字节,而不是unicode字符,所以你必须小心索引。在"Löwe"中,'e'位于(字节)索引4处,而不是3(playground)。但你仍然可以在你的情况下使用它,因为你没有直接使用索引(使用find代替...找到你需要的索引)

以下是切片的方法(红利,你不需要重新分配其他String):

// adding some unicode to check that everything works
// also ouside of ASCII
let line = "asdfapatterndf1老虎23<12";
let start_bytes = line.find("pattern").unwrap();
let mut result = &line[start_bytes..]; // result is from "pattern" to
                                   // the end, so "patterndf1老虎23<12"

// if there's a < let's check its byte index
if let Some(end) = result.find("<") {
    // and re-slice line accordingly (now result = "patterndf1老虎23")
    result = &line[start_bytes.. start_bytes+end];
}