Skip to content

str::find

str methods · Strings

Level: reference · for working programmers

One line: The byte offset of the first match, as Option<usize>None when there is none, never -1.

pub fn find<P: Pattern>(&self, pat: P) -> Option<usize>

Stable since 1.0.0.

The return is an Option, which is the whole difference from the C-family indexOf returning -1: there is no sentinel to forget to check, and the type system will not let you use the offset until you have dealt with the miss.

The offset is in bytes, and it is always on a character boundary, so it is safe to slice at:

fn main() {
    let s = "key=value";
    if let Some(i) = s.find('=') { println!("{:?} {:?}", &s[..i], &s[i + 1..]); }
}

That i + 1 is only right because '=' is one byte. For a multi-byte or &str pattern the end of the match is i + pat.len() — which is exactly the arithmetic split_once does for you, and the reason to prefer it for this shape.

A predicate pattern finds the first character satisfying it, which is how you locate the first digit or the first non-ASCII character in one call.

Example

str_find.rs in full — pasted here by tools/run_examples.py from the file CI compiles and runs.

fn main() {
    let s = "key=value=more";

    println!("{:?}", s.find('='));
    println!("{:?}", s.find("value"));
    println!("{:?}", s.find(char::is_numeric));   // None, not -1

    // Splitting by hand — correct, but the +1 is the pattern's byte length.
    if let Some(i) = s.find('=') {
        println!("{:?} / {:?}", &s[..i], &s[i + 1..]);
    }
    // The same thing, with no arithmetic to get wrong.
    println!("{:?}", s.split_once('='));

    // Byte offsets, so a wide character shifts everything after it.
    let wide = "héllo=x";
    println!("{:?} at byte {:?}", '=', wide.find('='));

    // First character matching a predicate.
    println!("{:?}", "abc123".find(char::is_numeric));
}

Verified output of str_find.rs — regenerated by tools/run_examples.py, never hand-typed.

Some(3)
Some(4)
None
"key" / "value=more"
Some(("key", "value=more"))
'=' at byte Some(6)
Some(3)

See also

str::find in the standard library ↗

Po polsku

Od find z Pythona — czy indexOf z Javy — różnią tę metodę dwie rzeczy. Po pierwsze zwraca Option<usize>, a nie -1: nie ma wartownika, o którego sprawdzeniu dałoby się zapomnieć, bo system typów nie wypuści przesunięcia, dopóki nie obsłużysz przypadku „nie znaleziono”. Po drugie liczba w środku to przesunięcie w bajtach, więc na polskim tekście nie zgadza się z pozycją znaku — "żółw=x".find('=') da Some(7), a nie Some(4), dokładnie tak jak "héllo=x" z przykładu powyżej daje Some(6). To przesunięcie zawsze wypada na granicy znaku, więc wolno przy nim ciąć, ale &s[i + 1..] jest poprawne wyłącznie wtedy, gdy wzorzec ma jeden bajt; koniec dopasowania to i + pat.len(), a najbezpieczniej niczego nie liczyć i sięgnąć po split_once.

Szukaj po polsku: wyszukiwanie w łańcuchu znaków · przesunięcie bajtowe · rust str find Option · rust split_once