Strings and Text Processing

trim() and Related Methods

str provides zero-allocation trimming and prefix/suffix stripping methods that adjust the start pointer and length of a &str slice without modifying or copying the underlying bytes.

Reference of Trimming and Stripping Methods

Method What It Removes Return Type
s.trim() Leading and trailing Unicode whitespace (char::is_whitespace) &str
s.trim_start() Leading Unicode whitespace only &str
s.trim_end() Trailing Unicode whitespace only &str
s.trim_ascii() Leading and trailing ASCII whitespace (' ', '\t', '\n', '\r', '\x0C') &str (const fn)
s.trim_matches(pat) Leading and trailing characters matching pat (char, &[char], or predicate) &str
s.trim_start_matches(pat) Leading characters or repeated prefix matching pat &str
s.trim_end_matches(pat) Trailing characters or repeated suffix matching pat &str
s.strip_prefix(pat) At most one leading occurrence of pat; returns None if absent Option<&str>
s.strip_suffix(pat) At most one trailing occurrence of pat; returns None if absent Option<&str>
Original: "   hello world\n " (ptr = p, len = 17)
              └───┬─────┘
s.trim():    "hello world"    (ptr = p + 3, len = 11 — zero heap allocation!)

Trimming Whitespace and Custom Delimiters

fn main() {
    let raw = "  \t  rust-2024 \r\n ";
    println!("trim():       {:?}", raw.trim());
    println!("trim_start(): {:?}", raw.trim_start());
    println!("trim_end():   {:?}", raw.trim_end());

    let wrapped = "***[IMPORTANT]***";
    println!(
        "trim_matches: {:?}",
        wrapped.trim_matches(&['*', '[', ']'][..])
    );
}
trim():       "rust-2024"
trim_start(): "rust-2024 \r\n "
trim_end():   "  \t  rust-2024"
trim_matches: "IMPORTANT"

Why You Usually Want strip_prefix() Instead of trim_start_matches()

A subtle bug arises when using trim_start_matches("prefix") or trim_end_matches("suffix") with a &str or character set:

  • trim_start_matches(pat) removes all repeated occurrences of pat and always returns a &str even if pat was not present.
  • strip_prefix(pat) and strip_suffix(pat) check whether s starts or ends with pat, remove exactly one occurrence, and return Some(rest) (or None if pat did not match):
fn main() {
    let token_header = "Bearer Bearer_secret";

    // `strip_prefix` removes "Bearer " once and returns `Option<&str>`:
    if let Some(token) = token_header.strip_prefix("Bearer ") {
        println!("Extracted token: '{token}'");
    }

    let path = "/var/log/app.log.log";
    println!("strip_suffix:     {:?}", path.strip_suffix(".log"));
    println!("trim_end_matches: {:?}", path.trim_end_matches(".log"));
}
Extracted token: 'Bearer_secret'
strip_suffix:     Some("/var/log/app.log")
trim_end_matches: "/var/log/app"