String#slice

str.slice(index) -> string or nil
str.slice(start, length) -> string or nil
str.slice(range) -> string or nil
str.slice(regexp) -> string or nil
str.slice(regexp, capture) -> string or nil
Returns: String or nil · Updated March 13, 2026 · String Methods
strings substring extract index range regex

The .slice method (and its alias []) extracts portions of a string using various indexing styles. It’s one of the most versatile string methods in Ruby, supporting integer positions, ranges, and regular expressions. When the requested substring doesn’t exist, these methods return nil instead of raising an error, making them safe to use without prior bounds checking.

Syntax

str.slice(index)           # Single integer index
str.slice(start, length)   # Start index and length
str.slice(range)           # Range of indices
str.slice(regexp)          # Regular expression match
str.slice(regexp, capture) # Regex with capture group

# The [] alias works identically
str[index]
str[start, length]
str[start..end]
str[regexp]
str[regexp, capture]

Parameters

ParameterTypeDescription
indexIntegerZero-based position of a single character
startIntegerStarting position for substring extraction
lengthIntegerNumber of characters to extract
rangeRangeA range of indices (inclusive or exclusive)
regexpRegexpA regular expression to match against
captureInteger or SymbolCapture group index (0 for full match) or name

Worked Examples

Example 1: Integer and range indexing

str = "Hello, World!"

# Single character at index
puts str.slice(0)      # => "H"
puts str.slice(7)      # => "W"
puts str.slice(20)     # => nil (out of bounds)

# Start and length
puts str.slice(0, 5)   # => "Hello"
puts str.slice(7, 5)   # => "World"
puts str.slice(7, 100)  # => "World!" (length exceeds string)

# Range (inclusive)
puts str.slice(0..4)   # => "Hello"
puts str.slice(7..12)  # => "World"

# Range (exclusive)
puts str.slice(0...5)  # => "Hello"
puts str.slice(7...12) # => "World"

Example 2: Regex and capture groups

str = "The price is $42.99"

# Match with regex
puts str.slice(/\d+/)          # => "42"
puts str.slice(/[A-Z]+/)        # => "The"

# Capture groups
puts str.slice(/(\d+)\.(\d+)/, 1)  # => "42" (first capture)
puts str.slice(/(\d+)\.(\d+)/, 2)  # => "99" (second capture)

# Named capture groups
text = "Date: 2024-01-15"
puts text.slice(/(?<year>\d{4})/, :year)  # => "2024"

# Regex that doesn't match
puts str.slice(/xyz/)           # => nil

Example 3: Negative indices

str = "Hello"

# Negative indices count from the end
puts str.slice(-1)      # => "o"
puts str.slice(-5)      # => "H"
puts str.slice(-6)      # => nil (out of bounds)

# Negative ranges
puts str.slice(-5..-1)  # => "Hello"
puts str.slice(-4...-1) # => "ello"
puts str.slice(-6..-1)  # => nil

Common Patterns

Safe string extraction with defaults

def get_code(input, default = "UNKNOWN")
  code = input.slice(/[A-Z]{3}/)
  code || default
end

get_code("ABC-123")    # => "ABC"
get_code("no-match")   # => "UNKNOWN"

Parsing structured data

line = "user:alice:admin"

username = line.slice(/:(.*):/, 1)
role = line.slice(/:([^:]+)$/, 1)

puts username  # => "alice"
puts role      # => "admin"

Truncating text

def truncate(text, max_length)
  return text if text.length <= max_length
  text.slice(0, max_length) + "..."
end

truncate("Hello, world!", 8)  # => "Hello, w..."

Character-by-character processing

str = "ruby"
5.times do |i|
  char = str.slice(i)
  break unless char
  puts "Char #{i}: #{char}"
end

# Output:
# Char 0: r
# Char 1: u
# Char 2: b
# Char 3: y

Extracting numbers from strings

phone = "Call me at 555-123-4567"

digits = phone.scan(/\d/).join
puts digits  # => "5551234567"

area_code = phone.slice(/\d{3}/)
puts area_code  # => "555"

See Also