Preview Ruby 4.1 is a preview. It can change before the final release. Switch to Ruby 4.0 →
String#byterindex
static VALUE
rb_str_byterindex_m(int argc, VALUE *argv, VALUE str)
{
VALUE sub;
VALUE initpos;
rb_len_t pos;
if (rb_scan_args(argc, argv, "11", &sub, &initpos) == 2) {
pos = NUM2LEN(initpos);
rb_len_t len = RSTRING_LEN(str);
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 = RSTRING_LEN(str);
}
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();
pos = RMATCH_BEG(match, 0);
return LEN2NUM(pos);
}
}
else {
StringValue(sub);
pos = rb_str_byterindex(str, sub, pos);
if (pos >= 0) return LEN2NUM(pos);
}
return Qnil;
}
Returns the 0-based integer index of a substring of self that is the last match for the given object (a string or Regexp) and offset, or nil if there is no such substring; the returned index is the count of bytes (not characters).
When object is a string, returns the index of the last found substring equal to object:
s = 'foo' # => "foo" s.size # => 3 # Three 1-byte characters. s.bytesize # => 3 # Three bytes. s.byterindex('f') # => 0 s.byterindex('o') # => 2 s.byterindex('oo') # => 1 s.byterindex('ooo') # => nil
When object is a Regexp, returns the index of the last found substring matching object; updates Regexp-related global variables:
s = 'foo' s.byterindex(/f/) # => 0 $~ # => #<MatchData "f"> s.byterindex(/o/) # => 2 s.byterindex(/oo/) # => 1 s.byterindex(/ooo/) # => nil $~ # => nil
The last match means starting at the possible last position, not the last of the longest matches:
s = 'foo' s.byterindex(/o+/) # => 2 $~ #=> #<MatchData "o">
To get the last longest match, use a negative lookbehind:
s = 'foo' s.byterindex(/(?<!o)o+/) # => 1 $~ # => #<MatchData "oo">
Or use method byteindex with negative lookahead:
s = 'foo' s.byteindex(/o+(?!.*o)/) # => 1 $~ #=> #<MatchData "oo">
Integer argument offset, if given, specifies the 0-based index of the byte where searching is to end.
When offset is non-negative, searching ends at byte position offset:
s = 'foo' s.byterindex('o', 0) # => nil s.byterindex('o', 1) # => 1 s.byterindex('o', 2) # => 2 s.byterindex('o', 3) # => 2
When offset is negative, counts backward from the end of self:
s = 'foo' s.byterindex('o', -1) # => 2 s.byterindex('o', -2) # => 1 s.byterindex('o', -3) # => nil
Raises IndexError if the byte at offset is not the first byte of a character:
s = "\uFFFF\uFFFF" # => "\uFFFF\uFFFF" s.size # => 2 # Two 3-byte characters. s.bytesize # => 6 # Six bytes. s.byterindex("\uFFFF") # => 3 s.byterindex("\uFFFF", 1) # Raises IndexError s.byterindex("\uFFFF", 2) # Raises IndexError s.byterindex("\uFFFF", 3) # => 3 s.byterindex("\uFFFF", 4) # Raises IndexError s.byterindex("\uFFFF", 5) # Raises IndexError s.byterindex("\uFFFF", 6) # => nil
Related: see Querying.
Ruby version changes
-
3.2
-
String#byteindexandString#byterindexhave been added. [Feature #13110]
-