Skip to content

str::split_once

str methods · Strings

Level: reference · for working programmers

One line: Splits at the first match into exactly two pieces, or returns None — the right tool for key=value.

pub fn split_once<P: Pattern>(&self, delimiter: P) -> Option<(&'_ str, &'_ str)>

Stable since 1.52.0.

Option<(&str, &str)> is what makes this better than splitn(2, ..): a string with no delimiter is a None the compiler makes you handle, not a one-element iterator that quietly behaves like a successful parse.

The delimiter itself is discarded, and it never appears in either piece. The right-hand piece keeps any later delimiters, so "a=b=c".split_once('=') is Some(("a", "b=c")).

Either side can be empty — "=v" gives Some(("", "v")) — so a well-formed line and a line with a missing key are both Some. Check for the empty key if it matters.

This is the parsing shape that removes the byte arithmetic from find: no i + 1, so a multi-byte delimiter cannot go wrong.

Example

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

fn main() {
    for line in ["key=value", "key=a=b", "=v", "k=", "bare"] {
        println!("{:<11} -> {:?}", format!("{line:?}"), line.split_once('='));
    }

    // The miss is a None you have to handle.
    let parsed: Vec<(&str, &str)> = ["a=1", "bad", "b=2"]
        .iter()
        .filter_map(|l| l.split_once('='))
        .collect();
    println!("{parsed:?}");

    // No byte arithmetic, so a multi-byte delimiter is safe.
    println!("{:?}", "left→right".split_once('→'));

    // A &str delimiter works too.
    println!("{:?}", "one :: two :: three".split_once(" :: "));
}

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

"key=value" -> Some(("key", "value"))
"key=a=b"   -> Some(("key", "a=b"))
"=v"        -> Some(("", "v"))
"k="        -> Some(("k", ""))
"bare"      -> None
[("a", "1"), ("b", "2")]
Some(("left", "right"))
Some(("one", "two :: three"))

See also

str::split_once in the standard library ↗

Po polsku

Do rozbicia klucz=wartość sięgaj po split_once, a nie po splitn(2, ..) — cała różnica siedzi w typie: brak separatora to None, które kompilator każe obsłużyć, a nie jednoelementowy iterator udający, że parsowanie się powiodło. Kto przychodzi z Pythona, zna tę pułapkę od drugiej strony: "bare".partition("=") zwraca ('bare', '', ''), czyli nieudany podział wygląda tam jak udany z pustą wartością, a split("=", 1) po cichu daje listę jednoelementową. Reszta zachowania jest mechaniczna i warto ją mieć w głowie: separator znika, prawa strona zatrzymuje wszystkie następne wystąpienia ("key=a=b" daje Some(("key", "a=b"))), a każda z połówek może być pusta, więc "=v" to wciąż Some(("", "v")) — pusty klucz sprawdzasz sam. Przy okazji znika arytmetyka na bajtach w stylu i + 1 po find, dzięki czemu separator wielobajtowy — , ale też ł czy półpauza — nie ma jak się rozjechać.

Szukaj po polsku: parsowanie klucz wartość · podział tekstu na dwie części · rust split_once vs splitn · rust split_once returns None