867

I have a string variable with content:

varMessage =   
            "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/liobrary.so"

In the string I have to find a sub-string:

"hi/thsid/sdfhsjdf/dfjsd/sdjfsdn\n"

"/my/name/is/balaji.so\n"
"call::myFunction(int const&)\n"

How can I find it? I need to determine whether the sub-string is present or not.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
BSalunke
  • 11,499
  • 8
  • 34
  • 68

10 Answers10

1600

You can use the include? method:

my_string = "abcdefg"
if my_string.include? "cde"
   puts "String includes 'cde'"
end
Dave Powers
  • 2,051
  • 2
  • 30
  • 34
Adam Lear
  • 38,111
  • 12
  • 81
  • 101
  • 121
    Remember that `include?` is case sensetive. So if `my_string` in the example above would be something like `"abcDefg"` (with an uppercase `D`), `include?("cde")` would return `false`. You may want to do a `downcase()` before calling `include?()`. – phortx Mar 25 '14 at 07:58
  • 4
    Include on it's own is not ideal as it can throw a NoMethodError if nil test = nil test.include?("test") NoMethodError: undefined method `include?' for nil:NilClass should always convert the value being included to the expected value:- test.to_s.include?("test") – Gary May 08 '18 at 21:24
  • 4
    @Gary's advice holds *if* your goal is to minimize exceptions raised in this part of the code. That is not always the best goal. Generally if you expect a string at this point in the code and a value is nil instead, that implies something unexpected has occurred and an exception being raised is appropriate. If the existence of a nil here is unexpected, using `to_s` will hide the problem and increase the distance between the source and the detection of the problem, making it harder to debug. – Luke Griffiths May 11 '20 at 22:11
  • Alternatively, avoid sending methods to nil with a safe navigation operator `test&.include?("test")` – David Aldridge Mar 30 '22 at 16:03
106

If case is irrelevant, then a case-insensitive regular expression is a good solution:

/bcd/i =~ 'aBcDe'   # returns nil if no match

or

/bcd/i === 'aBcDe'  # returns false if no match

This will also work for multi-line strings.

See Ruby's Regexp class for more information.

Clint Pachl
  • 10,848
  • 6
  • 41
  • 42
  • 15
    If you are matching against user input and using this technique, remember to use `Regexp.escape` on the string. For most use cases, `some_str.include? substr.downcase()` should work faster and be more readable. – Jacklynn Apr 24 '15 at 22:01
  • 8
    Using a regular expression this way isn't necessarily going to be faster than using `'aBcDe'.downcase.include?('bcd')`. Regex have their purpose but don't use them when the built-in methods are faster. Benchmarking with the actual data being tested can reveal much. – the Tin Man Mar 28 '16 at 20:33
  • 6
    This does NOT evaluate as true. It evaluates to 1 which is not true. – slindsey3000 Mar 16 '18 at 13:21
  • 3
    !!('aBcDe' =~ /bcd/i) will evaluate to true or false. Use the !! idiom – slindsey3000 Mar 16 '18 at 13:23
  • 4
    alternatively, use match? to return a boolean: `/bcd/i.match?('aBcDe')` – scrthq Mar 07 '20 at 17:53
  • 1
    @scrthq: Or for minimal characters for code golfing, use `===` instead, `/bcd/i==='aBcDe'`. `.match?` is definitely more descriptive for normal code though. – ShadowRanger Feb 23 '23 at 15:42
70

You can also do this...

my_string = "Hello world"

if my_string["Hello"]
  puts 'It has "Hello"'
else
  puts 'No "Hello" found'
end

# => 'It has "Hello"'

This example uses Ruby's String #[] method.

Oto Brglez
  • 4,113
  • 1
  • 26
  • 33
  • 3
    This is a neat trick I've not seen before. But `#include?` is still a little faster. – Scott Schupbach Jan 20 '17 at 02:09
  • 5
    `#include?` doesn't work when you are working with sentences with spaces inside because `#include` splits the sentence in words and then uses the words as separate array values. This works perfectly for sentences. +1 – luissimo Jan 25 '19 at 15:11
  • 1
    See Ruby's String [`[]`](https://ruby-doc.org/core-2.7.0/String.html#method-i-5B-5D) method for more information. – the Tin Man Feb 14 '20 at 04:01
  • 3
    @luissimo `include?` does not split the string. It simply checks if a string is or isn't within an other string. `'Hello World! How are you?'.include?('e y') #=> true` This answer does the same thing. `'Hello World! How are you?'['e y'] #=> "e y"` (which is truthy), `nil` is returned if there is no match (which is falsy). – 3limin4t0r Aug 14 '21 at 11:34
35

Expanding on Clint Pachl's answer:

Regex matching in Ruby returns nil when the expression doesn't match. When it does, it returns the index of the character where the match happens. For example:

"foobar" =~ /bar/  # returns 3
"foobar" =~ /foo/  # returns 0
"foobar" =~ /zzz/  # returns nil

It's important to note that in Ruby only nil and the boolean expression false evaluate to false. Everything else, including an empty Array, empty Hash, or the Integer 0, evaluates to true.

That's why the /foo/ example above works, and why.

if "string" =~ /regex/

works as expected, only entering the 'true' part of the if block if a match occurred.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
acib708
  • 1,573
  • 1
  • 13
  • 24
30

A more succinct idiom than the accepted answer above that's available in Rails (from 3.1.0 and above) is .in?:

my_string = "abcdefg"
if "cde".in? my_string
  puts "'cde' is in the String."
  puts "i.e. String includes 'cde'"
end

I also think it's more readable.

See the in? documentation for more information.

Note again that it's only available in Rails, and not pure Ruby.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
stwr667
  • 1,566
  • 1
  • 16
  • 31
  • 6
    This relies on rails, the OP asked for a ruby solution – dft Nov 13 '17 at 23:42
  • 3
    That's right, although since a significant proportion of Ruby developers are using Rails, I thought this might be a preferred solution for some due to its clarity and brevity. – stwr667 Nov 15 '17 at 01:53
  • 1
    See https://stackoverflow.com/a/4239625/128421. It's in Rails, but is easily accessed from regular Ruby using Rails' [Active Support Core Extensions](https://edgeguides.rubyonrails.org/active_support_core_extensions.html) which allow easy cherry-picking of small groups of methods such as only [`in?`](https://edgeguides.rubyonrails.org/active_support_core_extensions.html#in-questionmark). – the Tin Man Feb 14 '20 at 18:53
  • Correct @theTinMan. `"cde".in? my_string` in pure Ruby yields `NoMethodError`. But with `require 'active_support/core_ext/object/inclusion'` it works, which can be loaded either from [Rails](https://github.com/rails/rails) itself or from the cut-down [Active Support Core Extensions](https://github.com/rails/rails/tree/master/activesupport). – stwr667 Feb 16 '20 at 05:47
14

Ternary way

my_string.include?('ahr') ? (puts 'String includes ahr') : (puts 'String does not include ahr')

OR

puts (my_string.include?('ahr') ? 'String includes ahr' : 'String not includes ahr')
BSMP
  • 4,596
  • 8
  • 33
  • 44
Mauro
  • 1,241
  • 22
  • 26
13

You can use the String Element Reference method which is []

Inside the [] can either be a literal substring, an index, or a regex:

> s='abcdefg'
=> "abcdefg"
> s['a']
=> "a"
> s['z']
=> nil

Since nil is functionally the same as false and any substring returned from [] is true you can use the logic as if you use the method .include?:

0> if s[sub_s]
1>    puts "\"#{s}\" has \"#{sub_s}\""
1> else 
1*    puts "\"#{s}\" does not have \"#{sub_s}\""
1> end
"abcdefg" has "abc"

0> if s[sub_s]
1>    puts "\"#{s}\" has \"#{sub_s}\""
1> else 
1*    puts "\"#{s}\" does not have \"#{sub_s}\""
1> end
"abcdefg" does not have "xyz" 

Just make sure you don't confuse an index with a sub string:

> '123456790'[8]    # integer is eighth element, or '0'
=> "0"              # would test as 'true' in Ruby
> '123456790'['8']  
=> nil              # correct

You can also use a regex:

> s[/A/i]
=> "a"
> s[/A/]
=> nil
dawg
  • 98,345
  • 23
  • 131
  • 206
4

How to check whether a string contains a substring in Ruby?

When you say 'check', I assume you want a boolean returned in which case you may use String#match?. match? accepts strings or regexes as its first parameter, if it's the former then it's automatically converted to a regex. So your use case would be:

str = 'string'
str.match? 'strings' #=> false
str.match? 'string'  #=> true
str.match? 'strin'   #=> true
str.match? 'trin'    #=> true
str.match? 'tri'     #=> true

String#match? has the added benefit of an optional second argument which specifies an index from which to search the string. By default this is set to 0.

str.match? 'tri',0   #=> true
str.match? 'tri',1   #=> true
str.match? 'tri',2   #=> false
Sagar Pandya
  • 9,323
  • 2
  • 24
  • 35
2
user_input = gets.chomp
user_input.downcase!

if user_input.include?('substring')
  # Do something
end

This will help you check if the string contains substring or not

puts "Enter a string"
user_input = gets.chomp  # Ex: Tommy
user_input.downcase!    #  tommy


if user_input.include?('s')
    puts "Found"
else
    puts "Not found"
end
Prabhakar
  • 6,458
  • 2
  • 40
  • 51
0

In case you can not use one of the libs mentioned above, one could achieve the same with simple text search (this is ignoring cases because of downcase):

ADD_BUTTON_TEXTS = ["add to cart", "add to basket"].freeze
target_text = "AdD tO cArT"
ADD_BUTTON_TEXTS.each do |text|
  puts "Text was found" if target_text.downcase.include?(text)
end
d1jhoni1b
  • 7,497
  • 1
  • 51
  • 37