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.



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

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.


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 .


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.


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.


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')

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

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

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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.