SCALARs and strings

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.

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") 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: 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 and 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 — the left-to-right counterpart; identical argument conventions, returns the first occurrence

  • substr — typically the next call after a successful rindex, to slice the matched region or what follows it

  • length — 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 offset

  • split — when you want every segment delimited by SUBSTR, not just the last one

  • reverse — combined with index it is sometimes mistaken for a rindex substitute; rindex is both clearer and faster