index#
Find the position of a substring inside a string.
index scans STR left-to-right looking for the first occurrence of
SUBSTR and returns the zero-based position where it starts. No
regular-expression metacharacters, no case folding, no wildcards —
SUBSTR is matched literally, character for character. When the
search fails, index returns -1.
Synopsis#
index STR, SUBSTR
index STR, SUBSTR, POSITION
What you get back#
An integer. On a match, the zero-based offset of the first character
of SUBSTR inside STR. On no match, -1. The sentinel is the
idiomatic way to test:
if (index($line, $needle) >= 0) { ... } # found
if (index($line, $needle) == -1) { ... } # not found
POSITION and the return value use the same zero-based scale, so
you can feed one back into the other to walk every occurrence:
my $pos = -1;
while (($pos = index($text, $needle, $pos + 1)) != -1) {
push @hits, $pos;
}
How POSITION is interpreted#
POSITION is the earliest offset the match is allowed to start at.
The search still proceeds to the end of STR; POSITION does not
bound the search, it only shifts where it begins.
POSITIONomitted orundef— search from offset0.POSITIONnegative or otherwise before the start — treated as0.POSITIONpast the end ofSTR— treated as the end, so the only way to match is ifSUBSTRis the empty string (which matches at any offset, including the end).
An empty SUBSTR always matches, and matches at POSITION (clamped
into range). This follows from the “first position where SUBSTR
occurs” rule: the empty string occurs everywhere.
index("hello", ""); # 0
index("hello", "", 3); # 3
index("hello", "", 99); # 5 (clamped to end of string)
Examples#
Find a single character or a whole word:
index("Perl is great", "P"); # 0
index("Perl is great", "g"); # 8
index("Perl is great", "great"); # 8
Report a miss:
index("Perl is great", "Z"); # -1
Skip past an earlier match with POSITION to find the second
occurrence:
index("Perl is great", "e", 5); # 10
Walk every occurrence of a substring:
my $s = "abcabcabc";
my $p = -1;
while (($p = index($s, "bc", $p + 1)) != -1) {
print "hit at $p\n";
}
# hit at 1
# hit at 4
# hit at 7
A common idiom — test for containment without building a regex:
if (index($path, "/tmp/") != -1) {
warn "path touches /tmp";
}
Pairs naturally with substr to split on the first occurrence of a
separator:
my $line = "key=value=with=equals";
my $eq = index($line, "=");
my ($k, $v) = $eq >= 0
? (substr($line, 0, $eq), substr($line, $eq + 1))
: ($line, undef);
Edge cases#
Empty
SUBSTRmatches atPOSITION(clamped intoSTR).index($s, "")is0;index($s, "", $n)is$ncapped atlength $s. Never-1.Empty
STRwith non-emptySUBSTRreturns-1. EmptySTRwith emptySUBSTRreturns0.Negative
POSITIONis clamped to0.indexdoes not interpret negative offsets as “from the end” — that isrindex’s job, and even there the semantics differ.POSITIONpast the end ofSTRis clamped tolength STR, so only an emptySUBSTRcan match.Undef arguments stringify to
""and trigger anuninitializedwarning underuse warnings.index(undef, "x")is-1;index("abc", undef)is0(empty-substring rule).Characters, not bytes.
indexoperates on the logical character sequence of the string. For a string of wide characters, the returned offset is a character offset, not a byte offset. If you need byte offsets, downgrade or encode the string first (use bytesfor a lexical byte view, orEncode::encode_utf8to work on an octet string).Case sensitivity:
indexis case-sensitive. Lowercase both arguments first if you want a case-insensitive search, or use=~ /\Q$needle\E/iand@-/$-[0]to recover the position.
Differences from upstream#
Fully compatible with upstream Perl 5.42.
See also#
rindex— same matching rules, scans from the right and returns the offset of the last occurrence at or beforePOSITIONsubstr— extract the matched region onceindexhas located it, or replace it in placelength— upper bound for a validPOSITION; returns character length on the same scaleindexusespos— position tracking for regex-based scanning; use together withm//gwhen you need captures rather than a raw offsetsprintf— build the search string whenSUBSTRis assembled from parts;indextakes a literal, so prepare it first