--- name: rindex signature: 'rindex STR,SUBSTR,POSITION' signatures: - 'rindex STR,SUBSTR,POSITION' - 'rindex STR,SUBSTR' since: 5.0 status: documented categories: ["SCALARs and strings"] --- ```{index} single: rindex; Perl built-in ``` *[SCALARs and strings](../perlfunc-by-category)* # rindex Find the position of the **last** occurrence of a substring inside a string. `rindex` is the right-to-left counterpart of [`index`](index). It scans `STR` for `SUBSTR` and returns the zero-based offset of the rightmost match, or `-1` if no match exists. When `POSITION` is given, the search is constrained to matches whose starting offset is less than or equal to `POSITION` — that is, the last occurrence at or before that position. ## Synopsis ```perl rindex $str, $substr rindex $str, $substr, $position ``` ## What you get back An integer. Zero or positive means the zero-based offset of the rightmost match; `-1` means `SUBSTR` does not occur in `STR` (subject to the `POSITION` constraint, if any). Offsets are measured in **characters** when `STR` holds a character string, and in **bytes** when `STR` is a byte string. This matches [`index`](index) and the rest of Perl's string built-ins — the unit is whatever the string itself is using. ## How POSITION shapes the search `POSITION` is an **upper bound on the match's starting offset**, not on where scanning begins. The result satisfies: - `result <= POSITION` - `result + length(SUBSTR) <= length(STR)` (as always) Concretely: - `POSITION` omitted or [`undef`](undef) — search the whole string; return the rightmost match. - `POSITION` greater than or equal to `length(STR)` — behaves as if `POSITION` were `length(STR)`; the entire string is considered. - `POSITION` less than `0` — behaves as if `POSITION` were `0`; only a match starting at offset `0` can satisfy the constraint, so the return value is `0` when `STR` begins with `SUBSTR` and `-1` otherwise. - Empty `SUBSTR` — every offset from `0` to `length(STR)` is a valid match position, so `rindex` returns `min(POSITION, length(STR))` (or `length(STR)` when `POSITION` is omitted). Think of `POSITION` as "find the last match at or before here," not as "start scanning here." ## Examples Basic right-to-left search: ```perl rindex("banana", "a"); # 5 (the final 'a') rindex("banana", "na"); # 4 (last "na") rindex("banana", "z"); # -1 (not found) ``` Stepping backwards through every occurrence by using each result, minus one, as the next `POSITION`: ```perl my $str = "banana"; my $pos = length($str); while ((my $hit = rindex($str, "a", $pos - 1)) >= 0) { print "match at $hit\n"; # 5, 3, 1 $pos = $hit; } ``` `POSITION` as an upper bound — the match must **start** at or before it: ```perl rindex("banana", "na", 3); # 4? No: 4 > 3, so the match at 4 # is excluded; returns 2 rindex("banana", "na", 4); # 4 (match starting at 4 is allowed) ``` Empty `SUBSTR` matches at every offset, so the result is the capped position: ```perl rindex("banana", "", 4); # 4 rindex("banana", ""); # 6 (length of "banana") ``` Pairing with [`index`](index) to locate the last segment of a delimited string — a common idiom for splitting off a final extension or path component: ```perl my $path = "/usr/local/bin/perl"; my $slash = rindex($path, "/"); my $file = substr($path, $slash + 1); # "perl" ``` ## Edge cases - **Substring longer than string**: `rindex("abc", "abcd")` returns `-1`. No match can fit. - **Substring equals string**: `rindex("abc", "abc")` returns `0`. The last (and only) match starts at offset `0`. - **`POSITION` past the end**: `rindex($str, $sub, 9999)` behaves as if `POSITION` were `length($str)` — the entire string is scanned. - **`POSITION` is negative**: treated as `0`. `rindex("abc", "b", -5)` returns `-1` (no match can start at offset `0` or earlier); `rindex("abc", "a", -5)` returns `0`. - **`POSITION` is [`undef`](undef)**: same as omitting it. Under `use warnings` this emits an `uninitialized` warning. - **Empty `STR`, non-empty `SUBSTR`**: returns `-1`. - **Empty `STR`, empty `SUBSTR`**: returns `0`. - **Unicode**: for character strings (those the interpreter knows are text), offsets count characters, not bytes. A string flipped to byte semantics via `use bytes` or `encode_utf8` will report byte offsets instead. The rule mirrors [`index`](index) and [`substr`](substr). - **Tainted arguments**: the result inherits taint from `STR` and `SUBSTR` under `-T`. ## Differences from upstream Fully compatible with upstream Perl 5.42. ## See also - [`index`](index) — the left-to-right counterpart; identical argument conventions, returns the **first** occurrence - [`substr`](substr) — typically the next call after a successful `rindex`, to slice the matched region or what follows it - [`length`](length) — useful when computing the trailing slice: `substr($s, $hit + length($sub))` - [`pos`](pos) — for regex-driven scanning where you need the engine's match state rather than a single substring offset - [`split`](split) — when you want every segment delimited by `SUBSTR`, not just the last one - [`reverse`](reverse) — combined with [`index`](index) it is sometimes mistaken for a `rindex` substitute; `rindex` is both clearer and faster