Skip to content

str::trim_matches

str methods · Strings

Level: reference · for working programmers

One line: Trims a pattern from both ends, repeatedly — "xxhixx".trim_matches('x') is "hi".

pub fn trim_matches<P: Pattern>(&self, pat: P) -> &str
where
    for<'a> P::Searcher<'a>: DoubleEndedSearcher<'a>,

Stable since 1.0.0.

Not whitespace but whatever pattern you give it, and it keeps going as long as the ends match. That repetition is the difference from strip_prefix / strip_suffix, which remove one occurrence and tell you whether they found it.

The pattern must be a DoubleEndedSearcher, which in practice means a char, a &[char], or a closure — not a multi-character &str. "abcabc".trim_matches("abc") does not compile. Use the two one-sided methods when the pattern is a string:

fn main() {
    let s = "abcXabc";
    let inner = s.trim_start_matches("abc").trim_end_matches("abc");
    println!("{inner}");  // X
}

Removing quotes is the everyday use — and the everyday bug, because trim_matches('"') on "\"\"\"" eats all three, and on hi" removes a quote that had no partner. When the quotes must be balanced, strip_prefix and strip_suffix in an and_then chain is the honest version.

Example

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

fn main() {
    println!("{:?}", "xxhixx".trim_matches('x'));
    println!("{:?}", "--a-b--".trim_matches('-'));
    println!("{:?}", "1a2".trim_matches(char::is_numeric));
    println!("{:?}", "xy hi yx".trim_matches(&['x', 'y', ' '][..]));

    // A &str pattern is not accepted; chain the one-sided methods instead.
    let s = "abcXabc";
    println!("{:?}", s.trim_start_matches("abc").trim_end_matches("abc"));

    // The quote trap: it repeats, and it does not require a pair.
    println!("{:?}", "\"\"\"".trim_matches('"'));
    println!("{:?}", "hi\"".trim_matches('"'));

    // Balanced unquoting, which is usually what was meant.
    let quoted = "\"hi\"";
    let unquoted = quoted.strip_prefix('"').and_then(|s| s.strip_suffix('"'));
    println!("{unquoted:?}");
    println!("{:?}", "hi\"".strip_prefix('"').and_then(|s| s.strip_suffix('"')));
}

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

"hi"
"a-b"
"a"
"hi"
"X"
""
"hi"
Some("hi")
None

See also

str::trim_matches in the standard library ↗

Po polsku

trim_matches obcina wzorzec z obu końców i powtarza to tak długo, jak długo końce pasują — dlatego "xxhixx".trim_matches('x') daje "hi", a nie "xhix". Pierwsza pułapka jest widoczna od razu, bo kompilator ją zgłasza: wzorcem nie może być wieloznakowy &str (wymagany jest DoubleEndedSearcher), więc "abcabc".trim_matches("abc") się nie skompiluje i trzeba złożyć trim_start_matches("abc").trim_end_matches("abc"). Druga jest cichsza i widać ją w wyniku przykładu: przy zdejmowaniu cudzysłowów "\"\"\"".trim_matches('"') zjada wszystkie trzy i zostaje pusty łańcuch znaków, a "hi\"".trim_matches('"') usuwa cudzysłów, który nie miał pary. Gdy cudzysłowy mają być sparowane, uczciwą wersją jest strip_prefix('"').and_then(|s| s.strip_suffix('"')) — przy braku pary zwraca None zamiast po cichu psuć dane.

Szukaj po polsku: obcinanie znaków z końców łańcucha · usuwanie cudzysłowów w Ruscie · rust trim_matches vs strip_prefix · rust DoubleEndedSearcher pattern