Skip to content

Preview Ruby 4.1 is a preview. It can change before the final release. Switch to Ruby 4.0 →

instance method · added in Ruby 3.2

String#byterindex

(::Regexp | ::string pattern, ?::int offset) -> ::Integer?
byterindex(object, offset = self.bytesize) → integer or nil

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:

Example
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:

Example
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:

Example
s = 'foo'
s.byterindex(/o+/) # => 2
$~                 #=> #<MatchData "o">

To get the last longest match, use a negative lookbehind:

Example
s = 'foo'
s.byterindex(/(?<!o)o+/) # => 1
$~                       # => #<MatchData "oo">

Or use method byteindex with negative lookahead:

Example
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:

Example
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:

Example
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:

Example
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

  1. 3.2
See also #byteindex #bytes #bitwise_not! #bytesize also in 4.0 · 3.4 · 3.3 · 3.2