Search code examples
stringsplitrust

How can I split a string (String or &str) on more than one delimiter?


I want to be able to separate the string aabbaacaaaccaaa on the strings bb and cc but not on b or c. The example would result in aa,aacaaa,aaa.

I already can split a string on a single delimiter, and the words() function splits a string on ,\n and \t, so I figured it must be possible.


Solution

  • Unfortunately, you can't do this with the standard library right now. You can split on multiple char delimiters though, as words does. You need to give an array or slice of characters to split:

    for part in "a,bc;d".split([',', ';']) {
        println!(">{}<", part);
    }
    

    If you try with strings, however:

    for part in "a,bc;d".split([",", ";"]) {
        println!(">{}<", part);
    }
    

    You'll get the error:

    error[E0277]: expected a `FnMut<(char,)>` closure, found `[&str; 2]`
     --> src/main.rs:2:32
      |
    2 |     for part in "a,bc;d".split([",", ";"]) {
      |                          ----- ^^^^^^^^^^ expected an `FnMut<(char,)>` closure, found `[&str; 2]`
      |                          |
      |                          required by a bound introduced by this call
      |
      = help: the trait `FnMut<(char,)>` is not implemented for `[&str; 2]`
      = help: the following other types implement trait `Pattern<'a>`:
                &'b [char; N]
                &'b [char]
                [char; N]
      = note: required for `[&str; 2]` to implement `Pattern<'_>`
    note: required by a bound in `core::str::<impl str>::split`
    

    In nightly Rust, you could implement Pattern for your own type that includes a slice of strings.

    If you are cool with using a well-supported crate that isn't part of the standard library, you can use regex:

    use regex; // 1.4.5
    
    fn main() {
        let re = regex::Regex::new(r"bb|cc").unwrap();
        for part in re.split("aabbaacaaaccaaa") {
            println!(">{}<", part);
        }
    }