2016-06-13 74 views
2

我想在Rust中創建一個子字符串。它從一個字符串的出現開始,並在字符串的末尾減去四個字符或某個字符處結束。如何獲取Rust中兩個模式之間的子串?

我的第一種方法是

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

因爲鏽病的字符串是有效的UTF-8,因此字節,而不是基於CHAR這是錯誤的。

我的第二個方法是正確的,但太冗長:

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>(); 

是否有更簡單的方法來創建子?有沒有我找不到的標準庫的任何部分?

回答

5

我不記得其他語言中的內置庫函數的工作方式與您想要的完全相同(給出兩個模式之間的子串,或者第一個和最後一個之間,如果第二個模式不存在)。 我認爲你將不得不編寫一些自定義邏輯。

等效於「substring」函數的關閉正在切片。然而(正如你發現的那樣)它可以處理字節,而不是Unicode字符,所以你必須小心索引。在"Löwe"中,'e'位於(字節)索引4,而不是3(playground)。但你仍然可以在你的情況下使用它,因爲你沒有直接使用索引(使用find代替...找到你需要的索引)

以下是如何使用切片(獎金,你不需要重新分配等String S):

// 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]; 
} 
+0

注意:你實際上並不甚至需要第一個'to_string()',所以你並不需要一個單一的分配:) –

+0

@MatthieuM 。你是對的,謝謝。 :)更正 –

相關問題