Cómo verificar si una cadena contiene una subcadena en Ruby

731

Tengo una variable de cadena con contenido:

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"

En la cadena tengo que encontrar una subcadena:

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

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

¿Cómo puedo encontrarlo? Necesito determinar si la subcadena está presente o no.

BSalunke
fuente
3
Pregunta relacionada: stackoverflow.com/questions/3876246/…
Andrew Grimm
Consulte stackoverflow.com/a/3878656/128421 para obtener un desglose de varias formas de hacerlo.
El hombre de hojalata

Respuestas:

1366

Puedes usar el include?método:

my_string = "abcdefg"
if my_string.include? "cde"
   puts "String includes 'cde'"
end
Adam Lear
fuente
103
Recuerde que include?es sensible a mayúsculas y minúsculas. Entonces, si my_stringen el ejemplo anterior sería algo así "abcDefg"(con mayúscula D), include?("cde")volvería false. Es posible que desee hacer una downcase()antes de llamar include?().
phortx
44
Incluir por sí mismo no es ideal ya que puede arrojar un NoMethodError si nil test = nil test.include? ("Test") NoMethodError: método indefinido `include? ' for nil: NilClass siempre debe convertir el valor que se incluye al valor esperado: - test.to_s.include? ("test")
Gary
El consejo de @ Gary es válido si su objetivo es minimizar las excepciones planteadas en esta parte del código. Ese no es siempre el mejor objetivo. Por lo general, si espera una cadena en este punto del código y un valor es nulo, eso significa que ha ocurrido algo inesperado y que es apropiada una excepción. Si la existencia de un cero aquí es inesperada, el uso to_socultará el problema y aumentará la distancia entre la fuente y la detección del problema, lo que dificultará la depuración.
Luke Griffiths
88

Si el caso es irrelevante, entonces una expresión regular que no distingue entre mayúsculas y minúsculas es una buena solución:

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

Esto también funcionará para cadenas de varias líneas.

Vea la clase Regexp de Ruby para más información.

Clint Pachl
fuente
11
Si está comparando con la entrada del usuario y está utilizando esta técnica, recuerde usarla Regexp.escapeen la cadena. Para la mayoría de los casos de uso, some_str.include? substr.downcase()debería funcionar más rápido y ser más legible.
Jack
44
Usar una expresión regular de esta manera no necesariamente será más rápido que usarlo 'aBcDe'.downcase.include?('bcd'). Regex tiene su propósito, pero no los use cuando los métodos integrados son más rápidos. La evaluación comparativa con los datos reales que se están probando puede revelar mucho.
The Tin Man
3
Esto NO evalúa como verdadero. Se evalúa a 1, lo cual no es cierto.
slindsey3000
2
!! ('aBcDe' = ~ / bcd / i) se evaluará como verdadero o falso. Utilizar el !! idioma
slindsey3000
2
alternativamente, usa match? para devolver un booleano:/bcd/i.match?('aBcDe')
ferrell_io
45

También puedes hacer esto ...

my_string = "Hello world"

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

# => 'It has "Hello"'

Este ejemplo utiliza el #[]método de Ruby String .

Oto Brglez
fuente
2
Este es un buen truco que no he visto antes. Pero #include?aún es un poco más rápido.
Scott Schupbach
44
#include?no funciona cuando trabaja con oraciones con espacios en el interior porque #includedivide la oración en palabras y luego las usa como valores de matriz separados. Esto funciona perfectamente para las oraciones. +1
luissimo
Vea el []método String de Ruby para más información.
el hombre de hojalata
32

Ampliando la respuesta de Clint Pachl:

La coincidencia de expresiones regulares en Ruby regresa nilcuando la expresión no coincide. Cuando lo hace, devuelve el índice del personaje donde ocurre la coincidencia. Por ejemplo:

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

Es importante tener en cuenta que solo en Ruby nily la expresión booleana se falseevalúa como falsa. Todo lo demás, incluida una matriz vacía, un hash vacío o el entero 0, se evalúa como verdadero.

Es por eso que el /foo/ejemplo anterior funciona y por qué.

if "string" =~ /regex/

funciona como se esperaba, solo ingresa la parte 'verdadera' del ifbloque si se produce una coincidencia.

acib708
fuente
21

Una expresión más sucinta que la respuesta aceptada anterior que está disponible en Rails (desde 3.1.0 y superior) es .in?:

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

También creo que es más legible.

Consulte la in?documentación para más información.

Tenga en cuenta nuevamente que solo está disponible en Rails , y no en Ruby puro.

stwr667
fuente
2
Esto depende de los rieles, el OP solicitó una solución de rubí
dft
2
Así es, aunque dado que una proporción significativa de desarrolladores de Ruby está usando Rails, pensé que esta podría ser una solución preferida para algunos debido a su claridad y brevedad.
stwr667
1
Ver stackoverflow.com/a/4239625/128421 . Está en Rails, pero se puede acceder fácilmente desde Ruby regular usando las Extensiones de núcleo de soporte activo de Rails que permiten seleccionar fácilmente pequeños grupos de métodos, como solo in?.
El hombre de hojalata
Corregir @theTinMan. "cde".in? my_stringen puro Ruby cede NoMethodError. Pero con require 'active_support/core_ext/object/inclusion'esto funciona, que puede cargarse desde Rails o desde las extensiones de Active Support Core recortadas .
stwr667
16

Camino ternario

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

O

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

Puede usar el método de referencia de elemento de cadena que es[]

Dentro de []puede ser una subcadena literal, un índice o una expresión regular:

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

Dado que niles funcionalmente el mismo falsey cualquier subcadena devuelta []es trueque puede usar la lógica como si usara el 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" 

Solo asegúrese de no confundir un índice con una subcadena:

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

También puedes usar una expresión regular:

> s[/A/i]
=> "a"
> s[/A/]
=> nil
perro
fuente
2
esto es fenomenal
Craig
3

¿Cómo verificar si una cadena contiene una subcadena en Ruby?

Cuando dices 'comprobar', supongo que quieres que se devuelva un booleano, en cuyo caso puedes usarlo String#match?. match?acepta cadenas o expresiones regulares como su primer parámetro, si es el primero, se convierte automáticamente en una expresión regular. Entonces su caso de uso sería:

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

String#match?tiene el beneficio adicional de un segundo argumento opcional que especifica un índice desde el cual buscar la cadena. Por defecto, esto está configurado en 0.

str.match? 'tri',0   #=> true
str.match? 'tri',1   #=> true
str.match? 'tri',2   #=> false
Sagar Pandya
fuente
2
user_input = gets.chomp
user_input.downcase!

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

Esto lo ayudará a verificar si la cadena contiene una subcadena o no

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 Undurthi
fuente