rindex#
Find the position of the last occurrence of a substring inside a string.
rindex is the right-to-left counterpart of 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#
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 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 <= POSITIONresult + length(SUBSTR) <= length(STR)(as always)
Concretely:
POSITIONomitted orundef— search the whole string; return the rightmost match.POSITIONgreater than or equal tolength(STR)— behaves as ifPOSITIONwerelength(STR); the entire string is considered.POSITIONless than0— behaves as ifPOSITIONwere0; only a match starting at offset0can satisfy the constraint, so the return value is0whenSTRbegins withSUBSTRand-1otherwise.Empty
SUBSTR— every offset from0tolength(STR)is a valid match position, sorindexreturnsmin(POSITION, length(STR))(orlength(STR)whenPOSITIONis omitted).
Think of POSITION as “find the last match at or before here,” not
as “start scanning here.”
Examples#
Basic right-to-left search:
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:
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:
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:
rindex("banana", "", 4); # 4
rindex("banana", ""); # 6 (length of "banana")
Pairing with index to locate the last segment of a
delimited string — a common idiom for splitting off a final
extension or path component:
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")returns0. The last (and only) match starts at offset0.POSITIONpast the end:rindex($str, $sub, 9999)behaves as ifPOSITIONwerelength($str)— the entire string is scanned.POSITIONis negative: treated as0.rindex("abc", "b", -5)returns-1(no match can start at offset0or earlier);rindex("abc", "a", -5)returns0.POSITIONisundef: same as omitting it. Underuse warningsthis emits anuninitializedwarning.Empty
STR, non-emptySUBSTR: returns-1.Empty
STR, emptySUBSTR: returns0.Unicode: for character strings (those the interpreter knows are text), offsets count characters, not bytes. A string flipped to byte semantics via
use bytesorencode_utf8will report byte offsets instead. The rule mirrorsindexandsubstr.Tainted arguments: the result inherits taint from
STRandSUBSTRunder-T.
Differences from upstream#
Fully compatible with upstream Perl 5.42.
See also#
index— the left-to-right counterpart; identical argument conventions, returns the first occurrencesubstr— typically the next call after a successfulrindex, to slice the matched region or what follows itlength— useful when computing the trailing slice:substr($s, $hit + length($sub))pos— for regex-driven scanning where you need the engine’s match state rather than a single substring offsetsplit— when you want every segment delimited bySUBSTR, not just the last onereverse— combined withindexit is sometimes mistaken for arindexsubstitute;rindexis both clearer and faster