Como verificar se uma string contém uma substring no Ruby


731

Eu tenho uma variável de seqüência de caracteres com o conteúdo:

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"

Na string, tenho que encontrar uma sub-string:

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

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

Como posso encontrá-lo? Preciso determinar se a sub-string está presente ou não.



Consulte stackoverflow.com/a/3878656/128421 para obter informações detalhadas sobre várias maneiras de fazer isso.
the Tin Man

Respostas:


1366

Você pode usar o include?método:

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

103
Lembre-se de que include?é sensível a maiúsculas e minúsculas. Portanto, se my_stringno exemplo acima seria algo como "abcDefg"(com maiúsculas D), include?("cde")retornaria false. Você pode fazer uma downcase()antes de ligar include?().
Phortx

4
A inclusão por si só não é ideal, pois pode gerar um NoMethodError se nil test = nil test.include? ("Test") NoMethodError: método indefinido `include? ' para nil: NilClass sempre deve converter o valor que está sendo incluído no valor esperado: - test.to_s.include? ("test")
Gary

O conselho de @ Gary é válido se seu objetivo é minimizar as exceções levantadas nesta parte do código. Esse nem sempre é o melhor objetivo. Geralmente, se você espera uma string neste momento no código e um valor é nulo, isso implica que algo inesperado ocorreu e que uma exceção sendo levantada é apropriada. Se a existência de um zero aqui for inesperada, o uso to_socultará o problema e aumentará a distância entre a fonte e a detecção do problema, dificultando a depuração.
Luke Griffiths

88

Se o caso for irrelevante, uma expressão regular que não diferencia maiúsculas de minúsculas é uma boa solução:

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

Isso também funcionará para seqüências de várias linhas.

Veja a classe Regexp do Ruby para obter mais informações.


11
Se você estiver combinando com a entrada do usuário e estiver usando esta técnica, lembre-se de usar Regexp.escapea string. Para a maioria dos casos de uso, some_str.include? substr.downcase()deve funcionar mais rápido e ser mais legível.
Jack

4
Usar uma expressão regular dessa maneira não será necessariamente mais rápido do que usar 'aBcDe'.downcase.include?('bcd'). O Regex tem seu objetivo, mas não o utiliza quando os métodos internos são mais rápidos. O benchmarking com os dados reais sendo testados pode revelar muito.
o homem de lata

3
Isso NÃO é avaliado como verdadeiro. Ele avalia como 1 o que não é verdadeiro.
slindsey3000

2
!! ('aBcDe' = ~ / bcd / i) será avaliado como verdadeiro ou falso. Use o !! idioma
slindsey3000

2
alternativamente, use match? retornar um booleano:/bcd/i.match?('aBcDe')
ferrell_io

45

Você também pode fazer isso ...

my_string = "Hello world"

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

# => 'It has "Hello"'

Este exemplo usa o #[]método String do Ruby .


2
Este é um truque interessante que eu nunca vi antes. Mas #include?ainda é um pouco mais rápido.
Scott Schupbach

4
#include?não funciona quando você está trabalhando com frases com espaços internos, porque #includedivide a frase em palavras e, em seguida, usa as palavras como valores de matriz separados. Isso funciona perfeitamente para frases. 1
luissimo 25/01/19

Veja o []método String do Ruby para obter mais informações.
the Tin Man

32

Expandindo a resposta de Clint Pachl:

A correspondência de nilexpressões regulares em Ruby retorna quando a expressão não corresponde. Quando isso acontece, ele retorna o índice do personagem em que a correspondência acontece. Por exemplo:

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

É importante observar que somente no Ruby nile a expressão booleana é falseavaliada como falsa. Todo o resto, incluindo uma matriz vazia, hash vazio ou o número inteiro 0, é avaliado como verdadeiro.

É por isso que o /foo/exemplo acima funciona e por quê.

if "string" =~ /regex/

funciona como esperado, inserindo apenas a parte 'true' do ifbloco se ocorrer uma correspondência.


21

Um idioma mais sucinto do que a resposta aceita acima, disponível no Rails (a partir de 3.1.0 e superior) é .in?:

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

Eu também acho que é mais legível.

Consulte a in?documentação para obter mais informações.

Observe novamente que ele está disponível apenas no Rails , e não no Ruby puro.


2
Isso depende dos trilhos, o OP pediu uma solução em ruby ​​#
dft

2
Isso mesmo, embora uma vez que uma proporção significativa dos desenvolvedores Ruby esteja usando o Rails, eu pensei que essa poderia ser uma solução preferida para alguns devido à sua clareza e brevidade.
stwr667

1
Consulte stackoverflow.com/a/4239625/128421 . Está no Rails, mas é facilmente acessado a partir do Ruby comum usando as Extensões Principais de Suporte Ativo do Rails, que permitem a seleção fácil de pequenos grupos de métodos, como somente in?.
the Tin Man

Corrija @theTinMan. "cde".in? my_stringem rendimentos puros de Ruby NoMethodError. Mas com require 'active_support/core_ext/object/inclusion'ele funciona, que pode ser carregado no próprio Rails ou nas extensões de núcleo de suporte ativo ativadas .
stwr667 16/02

16

Caminho ternário

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

OU

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

11

Você pode usar o método String Element Reference que é[]

Dentro do []pode haver uma substring literal, um índice ou uma expressão regular:

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

Desde a nil funcionalmente é o mesmo que falsequalquer substring retornado, []é truepossível usar a lógica como se você usasse o método .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" 

Apenas certifique-se de não confundir um índice com uma sub string:

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

Você também pode usar uma regex:

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

2
isso é fenomenal
Craig

3

Como verificar se uma string contém uma substring no Ruby?

Quando você diz 'check', presumo que você queira um booleano retornado e, nesse caso, você poderá usar String#match?. match?aceita strings ou regexes como seu primeiro parâmetro; se é o primeiro, é automaticamente convertido em um regex. Portanto, seu caso de uso seria:

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

String#match?tem o benefício adicional de um segundo argumento opcional que especifica um índice a partir do qual pesquisar a string. Por padrão, isso está definido como 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

Isso ajudará você a verificar se a string contém substring ou não

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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.