Как проверить, содержит ли строка подстроку в Ruby


731

У меня есть строковая переменная с содержимым:

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"

В строке я должен найти подстроку:

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

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

Как я могу найти это? Мне нужно определить, присутствует ли подстрока или нет.



См. Stackoverflow.com/a/3878656/128421 для разбивки различных способов сделать это.
Жестянщик

Ответы:


1366

Вы можете использовать include?метод:

my_string = "abcdefg"
if my_string.include? "cde"
   puts "String includes 'cde'"
end

103
Помните, что include?это чувствительный случай. Так что если my_stringв приведенном выше примере будет что-то вроде "abcDefg"(с заглавной буквы D), include?("cde")вернется false. Вы можете сделать downcase()перед звонком include?().
phortx

4
Включить само по себе не идеально, так как он может выдать ошибку NoMethodError, если nil test = nil test.include? ("Test") NoMethodError: неопределенный метод `include? ' для nil: NilClass всегда должен преобразовывать включаемое значение в ожидаемое значение: - test.to_s.include? ("test")
Гэри

Совет @ Gary верен, если ваша цель - минимизировать исключения, возникающие в этой части кода. Это не всегда лучшая цель. Обычно, если вы ожидаете строку в этом месте в коде, а значение равно nil, это означает, что произошло что-то неожиданное, и возникла исключительная ситуация. Если существование nil здесь неожиданно, использование to_sскрывает проблему и увеличивает расстояние между источником и обнаружением проблемы, затрудняя отладку.
Люк Гриффитс

88

Если регистр не имеет значения, то регулярное выражение без учета регистра является хорошим решением:

'aBcDe' =~ /bcd/i  # evaluates as true

Это также будет работать для многострочных строк.

Смотрите Ruby's Regexp class для получения дополнительной информации.


11
Если вы сопоставляете данные с пользовательским вводом и используете эту технику, не забудьте использовать Regexp.escapeстроку. Для большинства случаев использования some_str.include? substr.downcase()должно работать быстрее и быть более читабельным.
Джек,

4
Использование регулярного выражения таким образом не обязательно будет быстрее, чем использование 'aBcDe'.downcase.include?('bcd'). У Regex есть свои цели, но не используйте их, когда встроенные методы работают быстрее. Сравнение с тестируемыми фактическими данными может многое показать.
Жестянщик

3
Это НЕ оценивается как правда. Это оценивает к 1, который не верен.
slindsey3000

2
!! ('aBcDe' = ~ / bcd / i) будет иметь значение true или false. Использовать !! идиома
slindsey3000

2
В качестве альтернативы использовать матч? вернуть логическое значение:/bcd/i.match?('aBcDe')
ferrell_io

45

Вы также можете сделать это ...

my_string = "Hello world"

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

# => 'It has "Hello"'

В этом примере используется #[]метод String Ruby .


2
Это хитрый трюк, которого я раньше не видел. Но #include?все еще немного быстрее.
Скотт

4
#include?не работает, когда вы работаете с предложениями с пробелами внутри, потому что #includeразделяет предложение на слова, а затем использует слова как отдельные значения массива. Это отлично работает для предложений. +1
Луиссимо

См. []Метод String в Ruby для получения дополнительной информации.
Жестянщик

32

Расширяя ответ Клинта Пахля:

Соответствие регулярному nilвыражению в Ruby возвращается, когда выражение не совпадает. Когда это происходит, он возвращает индекс символа, где происходит совпадение. Например:

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

Важно отметить, что только в Ruby nilи логическом выраженииfalse оценивается как ложное. Все остальное, включая пустой массив, пустой хэш или целое число 0, оценивается как true.

Вот почему /foo/приведенный выше пример работает и почему.

if "string" =~ /regex/

работает как положено, вводя «истинную» часть ifблока только в случае совпадения.


21

Более краткая идиома, чем принятый выше ответ, который доступен в Rails (от 3.1.0 и выше) .in?:

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

Я также думаю, что это более читабельно.

Смотрите in?документацию для получения дополнительной информации.

Обратите внимание, что он доступен только в Rails , а не на чистом Ruby.


2
Это опирается на рельсы, ОП просил решение рубинового
ТСП

2
Это верно, хотя, поскольку значительная часть разработчиков Ruby использует Rails, я подумал, что для некоторых это может быть предпочтительным решением из-за его ясности и краткости.
stwr667

1
См. Stackoverflow.com/a/4239625/128421 . Он находится в Rails, но к нему легко получить доступ из обычного Ruby с помощью расширений ядра активной поддержки Rails, которые позволяют легко выбирать небольшие группы методов, например только in?.
Жестянщик

Исправьте @theTinMan. "cde".in? my_stringв чистом рубиновом урожае NoMethodError. Но с require 'active_support/core_ext/object/inclusion'этим работает, который может быть загружен либо из самого Rails , либо из урезанных расширений Active Support Core .
stwr667

16

Троичный путь

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

ИЛИ

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

11

Вы можете использовать метод String Element Reference, который[]

Внутри []может быть литеральная подстрока, индекс или регулярное выражение:

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

Поскольку nilфункционально такой же, как falseи любая подстрока, возвращаемая из [], trueвы можете использовать логику, как если бы вы использовали метод .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" 

Просто убедитесь, что вы не путаете индекс с подстрокой:

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

Вы также можете использовать регулярное выражение:

> s[/A/i]
=> "a"
> s[/A/]
=> nil

2
это феноменально
Крейг

3

Как проверить, содержит ли строка подстроку в Ruby?

Когда вы говорите «чек», я предполагаю, что вы хотите вернуть логическое значение, и в этом случае вы можете использовать String#match?. match?принимает строки или регулярные выражения в качестве первого параметра, если он первый, то он автоматически преобразуется в регулярное выражение. Таким образом, ваш вариант использования будет:

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

String#match?имеет дополнительное преимущество необязательного второго аргумента, который указывает индекс для поиска строки. По умолчанию это установлено на 0.

str.match? 'tri',0   #=> true
str.match? 'tri',1   #=> true
str.match? 'tri',2   #=> false

2
user_input = gets.chomp
user_input.downcase!

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

Это поможет вам проверить, содержит ли строка подстроку или нет

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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.