rubyguides

String#match?

regexp.match?(string) -> true or false

The match? method performs a regex match and returns true or false without creating MatchData objects. This makes it faster than match when you only need to know if there’s a match.

Basic Usage

# Simple matching
/relo/.match?("Hello")     # => true
/relo/.match?("World")     # => false

The return value from match? is a simple boolean, so you can drop it directly into an if condition without worrying about truthiness quirks. Methods like =~ return an integer position or nil, and 0 is a valid match position that evaluates as falsy in Ruby, which can lead to subtle bugs. A plain true or false keeps the intent unambiguous and the control flow easy to reason about.

Performance Advantage

# match? is faster because it doesn't create MatchData
email = "user@example.com"
pattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/

# With match? - just boolean check
pattern.match?(email)  # => true

# With match - creates MatchData object (slower)
pattern.match(email)   # => #<MatchData "user@example.com">

Practical Examples

The examples below show match? applied to real-world patterns, starting with validation and moving through conditional logic, multiple-pattern checks, and the optional position parameter. Each example keeps the focus on the boolean result rather than match data, so you can see how the method fits into everyday Ruby code without the overhead of MatchData allocation.

Validation

def valid_email?(email)
  /^[^\s@]+@[^\s@]+\.[^\s@]+$/.match?(email)
end

valid_email?("test@example.com")  # => true
valid_email?("invalid")           # => false

This validation example turns a regular expression into a readable predicate method. The name valid_email? reads like a question, and the body answers it with a single boolean-producing call. Because match? creates no intermediate objects, the method stays lightweight even when called repeatedly inside a loop or on every request in a web application, keeping the code both clear and efficient under load.

Conditional Processing

text = "Error: Something went wrong"

if /Error/.match?(text)
  puts "Errors found in: #{text}"
end

The conditional example places match? inside an if statement, which is the most direct way to branch on the presence of a pattern. Because the method returns a plain boolean, there is no risk of a truthy MatchData object slipping through when the match position happens to be zero. That subtle bug can occur with =~ and index checks, but match? avoids it entirely by always returning either true or false.

Multiple Patterns

patterns = [/ruby/, /python/, /go/]
text = "I love programming in ruby"

patterns.any? { |p| p.match?(text) }  # => true

Pairing any? with a list of patterns is a natural fit for checking whether input matches any of several known formats. Each pattern gets a boolean check, and the iteration stops as soon as one succeeds. That short-circuit behavior keeps the cost proportional to the number of patterns only in the worst case, so it scales well for small-to-medium pattern lists inside validation pipelines and routing logic.

With position (Ruby 2.7+)

# Can specify start position
"hello world".match?(/world/, 6)  # => true
"hello world".match?(/world/, 0)  # => false

The position parameter lets you skip a known prefix and search only the remainder of a string. When processing structured text where the first few characters are a fixed header, pass the header length as the offset to avoid matching inside that region. This keeps the pattern focused on the part that actually varies, which often means the regular expression can be simpler because it does not need to account for the header at all.

Return Value

# Returns true or false
result = /cat/.match?("concatenation")
puts result  # => true (substring exists)

# No MatchData created
result = /(\d+)/.match?("abc123")
puts result  # => true, but $1 is nil (no capture)

When match? finds a match, it returns true and nothing else. No capture groups are populated, no $1 or $~ is set, and no MatchData object lingers afterward. This clean separation makes the method ideal inside loops and validation helpers where the surrounding code never inspects the matched content. If you need the matched text later, switch to match and keep the returned MatchData object for further inspection.

Comparison with other methods

pattern = /\d+/

# match? - just boolean, no MatchData
pattern.match?("abc123")  # => true

# match - returns MatchData or nil
pattern.match("abc123")   # => #<MatchData "123">

# =~ - returns position or nil
pattern =~ "abc123"       # => 3

Use Cases

  • Validation checks
  • Conditional branching based on presence
  • Performance-critical code
  • When you don’t need match details

when a boolean match is enough

match? is the right choice when you only care about whether the pattern is present and you do not need capture groups or match data. That makes it a clean fit for validation, guards, and quick checks inside hot paths. By skipping the extra object creation, the method keeps the intent simple and the implementation efficient.

It is also a good reminder to separate “do we have a match?” from “what exactly matched?” When those concerns stay separate, the calling code can choose the lighter method most of the time and reach for a fuller match only when the data is actually needed. That keeps regular checks fast without giving up the option to inspect details later.

using a fast check in hot paths

In performance-sensitive code, a boolean check can be easier to justify than building a match object that will never be used. That is why match? fits nicely in guards, filters, and validation steps that run often. It keeps the call site honest about what the program needs right now, which is a simple yes or no. When the surrounding logic eventually needs more detail, it can switch to a fuller match at that point instead of paying for it on every pass.

choosing the lighter option by default

For code that checks the same pattern many times, the lighter return value can make the intent feel sharper and the work feel smaller. That is useful in loops, validations, and search helpers where the surrounding branch only needs to know whether to continue. By keeping the result boolean, match? leaves the detailed match path available without forcing every call to take it.

See Also