str::match_indices¶
Level: reference · for working programmers
One line: Every match paired with the byte offset it starts at — (usize, &str), and the offsets are safe to slice with.
Stable since 1.5.0.
find gives you the first match's offset; this gives you all of them. It is the tool for building a highlighter, a replace-with-context, or any job that needs to know where each hit was rather than just how many there were.
The offset is the start of the match; the end is i + m.len(), so &s[i..i + m.len()] is the match itself and the text between hits is what split would have given you.
Non-overlapping and left to right, exactly like matches.
Example¶
str_match_indices.rs in full — pasted here by tools/run_examples.py from the file CI compiles and runs.
fn main() {
let s = "the rain in spain";
for (i, m) in s.match_indices("in") {
println!("byte {i:>2}: {m:?} ...{:?}", &s[i..(i + m.len() + 2).min(s.len())]);
}
// Offsets plus lengths reconstruct both the matches and the gaps.
let hits: Vec<(usize, &str)> = s.match_indices("in").collect();
println!("{hits:?}");
println!("{:?}", s.split("in").collect::<Vec<&str>>());
// Marking up every hit.
let mut out = String::new();
let mut last = 0;
for (i, m) in s.match_indices("in") {
out.push_str(&s[last..i]);
out.push('[');
out.push_str(m);
out.push(']');
last = i + m.len();
}
out.push_str(&s[last..]);
println!("{out}");
}
Verified output of str_match_indices.rs — regenerated by tools/run_examples.py, never hand-typed.
byte 6: "in" ..."in i"
byte 9: "in" ..."in s"
byte 15: "in" ..."in"
[(6, "in"), (9, "in"), (15, "in")]
["the ra", " ", " spa", ""]
the ra[in] [in] spa[in]
See also¶
str::matches— the matches without their offsetsstr::rmatch_indices— the same, from the backstr::find— just the first offsetstr::replace— when the goal is substitution rather than inspection
str::match_indices in the standard library ↗
Po polsku¶
match_indices zwraca pary (usize, &str), a ta liczba to przesunięcie w bajtach, nie numer znaku — różnica, której w Pythonie nie ma i o którą w polskim tekście łatwo się potknąć: w "żaba żaba" drugie wystąpienie zaczyna się na bajcie 6, choć na znaku 5, bo ż zajmuje w UTF-8 dwa bajty. To nie usterka, tylko sedno metody: offset pochodzi z prawdziwego dopasowania, więc z definicji leży na granicy znaku i wycinek &s[i..i + m.len()] nigdy nie wywoła paniki — inaczej niż indeks policzony na piechotę. Gdy chcesz pokazać człowiekowi „znaleziono na pozycji N", przelicz to osobno przez s[..i].chars().count(); a jeżeli interesuje cię tekst pomiędzy trafieniami, to dokładnie to, co zwróciłby split() z tym samym wzorcem.
Szukaj po polsku: pozycja znaku a pozycja bajtu · wyszukiwanie wszystkich wystąpień · przesunięcie w bajtach · rust match_indices byte offset · rust find all occurrences in string