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

JDe*_*ler 5 string rust

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

我的第一个方法是

string[string.find("pattern").unwrap()..string.len()-5]
Run Code Online (Sandbox Code Playgroud)

这是错误的,因为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>();
Run Code Online (Sandbox Code Playgroud)

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

Pao*_*lla 10

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

相当于"子串"函数的关闭是切片.然而(正如你所发现的)它适用于字节,而不是unicode字符,所以你必须小心索引.在"Löwe",'e'是(字节)索引4,而不是3(游乐场).但你仍然可以在你的情况下使用它,因为你没有直接使用索引(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_or(0); //index where "pattern" starts
                                                     // or beginning of line if 
                                                     // "pattern" not found
let end_bytes = line.find("<").unwrap_or(line.len()); //index where "<" is found
                                                      // or end of line

let result = &line[start_bytes..end_bytes]; //slicing line, returns patterndf1??23
Run Code Online (Sandbox Code Playgroud)