Question

How to Check Whether a String Contains a Substring in Ruby

rubystring

Question

I have a Ruby string variable containing multiple lines, for example:

var_message = \
  "hi/thsid/sdfhsjdf/dfjsd/sdjfsdn\n" \
  "/my/name/is/balaji.so\n" \
  "call::myFunction(int const&)\n" \
  "void::secondFunction(char const&)\n" \
  "this/is/last/line/library.so"

I want to check whether this multi-line substring exists inside it:

target = \
  "hi/thsid/sdfhsjdf/dfjsd/sdjfsdn\n" \
  "/my/name/is/balaji.so\n" \
  "call::myFunction(int const&)\n"

How can I determine whether this substring is present in the original string?

Short Answer

By the end of this page, you will understand how to check whether one string appears inside another in Ruby. You will learn the simplest method with include?, when to use regular expressions instead, how multiline matching works, and what common mistakes to avoid with newline characters and spacing.

Concept

In Ruby, a substring is just a smaller string that appears inside a larger string. If you want to know whether a string contains another string exactly, the most direct tool is:

big_string.include?(small_string)

This returns:

  • true if the substring exists
  • false if it does not

This matters because substring checks are common in real programs:

  • searching logs
  • validating file contents
  • parsing generated output
  • checking API responses
  • detecting commands or patterns in text

In your case, the main idea is that Ruby treats a multiline string as a normal string containing newline characters (\n). That means you can search for a block of text across multiple lines the same way you search for a single word, as long as the text matches exactly.

If you need exact text matching, use include?.

If you need pattern matching such as flexible spacing, optional text, or wildcards, use a regular expression with match? or =~.

Mental Model

Think of a string like one long strip of paper.

Even if it looks like multiple lines on the screen, Ruby still sees it as a sequence of characters:

  • letters
  • symbols
  • spaces
  • newline characters

Checking for a substring is like asking:

Does this smaller strip of paper appear somewhere inside the larger strip, character for character?

If every character matches in the same order, including \n, Ruby returns true.

If even one newline, space, or character is different, the match fails.

Take Quiz

Syntax and Examples

Basic syntax

string.include?(substring)

Simple example

message = "Hello Ruby world"
puts message.include?("Ruby")
# true

puts message.include?("Python")
# false

include? checks for an exact substring.

Multiline example

var_message = \
  "hi/thsid/sdfhsjdf/dfjsd/sdjfsdn\n" \
  "/my/name/is/balaji.so\n" \
  "call::myFunction(int const&)\n" \
  "void::secondFunction(char const&)\n" \
  "this/is/last/line/library.so"

target = \
  "hi/thsid/sdfhsjdf/dfjsd/sdjfsdn\n" \
  "/my/name/is/balaji.so\n" \
  "call::myFunction(int const&)\n"

puts var_message.include?(target)
# true

Because the first three lines appear exactly in var_message, Ruby returns true.

Using a heredoc for readability

For multiline text, heredocs are often easier to read:

var_message = <<~TEXT
  hi/thsid/sdfhsjdf/dfjsd/sdjfsdn
  /my/name/is/balaji.so
  call::myFunction(int const&)
  void::secondFunction(char const&)
  this/is/last/line/library.so
TEXT

target = <<~TEXT
  hi/thsid/sdfhsjdf/dfjsd/sdjfsdn
  /my/name/is/balaji.so
  call::myFunction(int const&)
TEXT

puts var_message.include?(target)
# true

This is often the cleanest way to work with multiline strings in Ruby.

Pattern matching with regex

If the text may vary slightly, use a regular expression:

message = "call::myFunction(int const&)\nvoid::secondFunction(char const&)"

puts message.match?(/call::myFunction\(int const&\)/)
# true

Use this only when you need patterns, not exact text.

Step by Step Execution

Example

text = "apple\nbanana\ncarrot\n"
part = "banana\ncarrot\n"

puts text.include?(part)

Step-by-step

  1. text stores one string:

    apple\nbanana\ncarrot\n
    
  2. part stores another string:

    banana\ncarrot\n
    
  3. Ruby checks whether the exact characters from part appear somewhere inside text.

  4. It compares character sequences, including newline characters.

  5. It finds this exact section inside text:

    banana\ncarrot\n
    
  6. include? returns true.

What if one newline is missing?

text = "apple\nbanana\ncarrot\n"
part = "banana\ncarrot"

puts text.include?(part)

This may still return true if that exact shorter sequence exists.

But if your expected text includes a newline and the source does not, or vice versa, the result can change. That is why exact formatting matters in substring searches.

Real World Use Cases

Where this is used

  • Log scanning: check whether a log contains a known error block
  • API testing: verify that a response body contains expected text
  • Code generation tools: confirm generated output includes required lines
  • File processing: search configuration files for a section
  • Security checks: detect dangerous commands or suspicious input
  • Build scripts: verify compiler or test output contains expected markers

Example: checking a log snippet

log = File.read("app.log")

if log.include?("ERROR: database connection failed")
  puts "Found database error"
end

Example: checking multiline output

output = <<~TEXT
  Step 1 completed
  Step 2 completed
  Deployment successful
TEXT

expected = <<~TEXT
  Step 2 completed
  Deployment successful
TEXT

puts output.include?(expected)
# true
Take Quiz

Real Codebase Usage

In real Ruby projects, developers usually choose the substring method based on how strict the match must be.

Common pattern: exact text check

if response.body.include?("success")
  puts "Request worked"
end

Use this when the text must appear exactly.

Common pattern: guard clause

def process_output(text)
  return unless text.include?("call::myFunction")

  puts "Function call found"
end

This avoids extra nesting and exits early when the required text is missing.

Common pattern: file validation

content = File.read("config.txt")
required_block = "start\nvalue=true\nend\n"

raise "Missing config block" unless content.include?(required_block)

Common pattern: regex for flexible matching

if output.match?(/call::\w+\(.*\)/)
  puts "Found a function-like line"
end

This is useful when the exact name or parameters may change.

Common pattern: normalize before searching

Sometimes developers clean text first:

normalized = text.gsub("\r\n", "\n")
puts normalized.include?(target)

This helps when text comes from different systems and line endings are inconsistent.

Common Mistakes

1. Forgetting that newlines matter

Broken example:

text = "a\nb\nc\n"
part = "a b c"

puts text.include?(part)
# false

Why it fails:

  • text contains newline characters
  • part contains spaces instead

Fix:

part = "a\nb\nc"

2. Using == instead of include?

Broken example:

puts text == part

== checks whether both strings are completely identical. It does not check whether one is contained inside the other.

Fix:

puts text.include?(part)

3. Ignoring Windows line endings

Some text uses \r\n instead of \n.

Broken example:

text = "a\r\nb\r\n"
part = "a\nb\n"

puts text.include?(part)
# false

Fix by normalizing line endings:

normalized = text.gsub("\r\n", "\n")
puts normalized.include?(part)

4. Accidental extra spaces

Broken example:

text = "call::myFunction(int const&)\n"
part = "call::myFunction(int const&) \n"

puts text.include?(part)
# false

That extra space changes the string.

5. Using regex when simple text search is enough

This is not always wrong, but it can make code harder to read.

Too complex:

text.match?(/hi\/thsid\/sdfhsjdf/)

Simpler:

text.include?("hi/thsid/sdfhsjdf")

Comparisons

MethodBest forReturnsNotes
include?Exact substring searchtrue / falseSimplest and most common
match?Pattern matching with regextrue / falseGood for flexible matching
=~Regex search with positionindex or nilOlder style, still useful
indexFind substring positioninteger or nilUseful if you need location
==Full string equalitytrue / falseNot for substring checks

Example comparison

text = "hello ruby world"

puts text.include?("ruby")   # true
puts text.index("ruby")      # 6
puts text.match?(/ruby/)      # true
puts(text =~ /ruby/)          # 6
puts text == "ruby"          # false

When to choose what

  • Use include? for exact text presence
  • Use index when you also need the position
  • Use match? for regex-based pattern matching
  • Use == only when both strings must be completely the same
Take Quiz

Cheat Sheet

Quick reference

Exact substring check

text.include?(part)

Get position of substring

text.index(part)
# returns integer or nil

Regex check

text.match?(/pattern/)

Multiline strings

text = <<~TEXT
  line1
  line2
TEXT

Important rules

  • include? checks exact characters
  • Newlines like \n are part of the string
  • Spaces must match exactly
  • == checks whole-string equality, not containment
  • Normalize line endings if text may use \r\n

Useful normalization

text = text.gsub("\r\n", "\n")

If you need a boolean result

  • include? returns true or false
  • match? returns true or false
  • index returns a number or nil

FAQ

How do I check if a string contains another string in Ruby?

Use include?:

text.include?(part)

It returns true or false.

Can Ruby search for a multiline substring?

Yes. A multiline string is still just a string with newline characters. If the exact sequence appears, include? will return true.

What is the difference between include? and match? in Ruby?

  • include? checks exact text
  • match? checks a regular expression pattern

Use include? unless you need flexible matching.

Why is my substring check failing even though the text looks correct?

Common reasons:

  • different newline characters (\n vs \r\n)
  • extra spaces
  • missing punctuation
  • case differences

How can I ignore line ending differences in Ruby?

Normalize the string first:

text = text.gsub("\r\n", "\n")

Can I find where the substring occurs, not just whether it exists?

Yes, use index:

text.index(part)

It returns the starting position or nil.

Is String#include? case-sensitive in Ruby?

Yes. "Ruby".include?("ruby") returns false.

Should I use regex for all string searches?

No. For exact substring checks, include? is simpler and easier to read.

Take Quiz

Mini Project

Description

Build a small Ruby script that checks whether a required multiline block exists inside a larger text body. This mirrors real tasks such as validating logs, checking generated files, or verifying expected output from a command.

Goal

Create a Ruby program that searches a multiline string and prints whether the target block was found.

Requirements

  • Store a multiline source string in a variable
  • Store a multiline target string in another variable
  • Check whether the target appears inside the source
  • Print a success message if found
  • Print a different message if not found
Take Quiz

Keep learning

Related questions

View more