Maintenance Ruby 3.3 gets fixes, but no new features. Switch to Ruby 4.0 →
String#byterindex
static VALUE
rb_str_byterindex_m(int argc, VALUE *argv, VALUE str)
{
VALUE sub;
VALUE initpos;
long pos, len = RSTRING_LEN(str);
if (rb_scan_args(argc, argv, "11", &sub, &initpos) == 2) {
pos = NUM2LONG(initpos);
if (pos < 0 && (pos += len) < 0) {
if (RB_TYPE_P(sub, T_REGEXP)) {
rb_backref_set(Qnil);
}
return Qnil;
}
if (pos > len) pos = len;
}
else {
pos = len;
}
str_ensure_byte_pos(str, pos);
if (RB_TYPE_P(sub, T_REGEXP)) {
if (rb_reg_search(sub, str, pos, 1) >= 0) {
VALUE match = rb_backref_get();
struct re_registers *regs = RMATCH_REGS(match);
pos = BEG(0);
return LONG2NUM(pos);
}
}
else {
StringValue(sub);
pos = rb_str_byterindex(str, sub, pos);
if (pos >= 0) return LONG2NUM(pos);
}
return Qnil;
}
Returns the Integer byte-based index of the last occurrence of the given substring, or nil if none found:
'foo'.byterindex('f') # => 0 'foo'.byterindex('o') # => 2 'foo'.byterindex('oo') # => 1 'foo'.byterindex('ooo') # => nil
Returns the Integer byte-based index of the last match for the given Regexp regexp, or nil if none found:
'foo'.byterindex(/f/) # => 0 'foo'.byterindex(/o/) # => 2 'foo'.byterindex(/oo/) # => 1 'foo'.byterindex(/ooo/) # => nil
The last match means starting at the possible last position, not the last of longest matches.
'foo'.byterindex(/o+/) # => 2 $~ #=> #<MatchData "o">
To get the last longest match, needs to combine with negative lookbehind.
'foo'.byterindex(/(?<!o)o+/) # => 1 $~ #=> #<MatchData "oo">
Or String#byteindex with negative lookforward.
'foo'.byteindex(/o+(?!.*o)/) # => 1 $~ #=> #<MatchData "oo">
Integer argument offset, if given and non-negative, specifies the maximum starting byte-based position in the
string to _end_ the search: 'foo'.byterindex('o', 0) # => nil 'foo'.byterindex('o', 1) # => 1 'foo'.byterindex('o', 2) # => 2 'foo'.byterindex('o', 3) # => 2
If offset is a negative Integer, the maximum starting position in the string to end the search is the sum of the string’s length and offset:
'foo'.byterindex('o', -1) # => 2 'foo'.byterindex('o', -2) # => 1 'foo'.byterindex('o', -3) # => nil 'foo'.byterindex('o', -4) # => nil
If offset does not land on character (codepoint) boundary, IndexError is raised.
Related: String#byteindex.
Ruby version changes
-
3.2
-
String#byteindexandString#byterindexhave been added. [Feature #13110]
-