Ruby Language
Expresiones regulares y operaciones basadas en expresiones regulares
Buscar..
Grupos, nombrados y otros.
Ruby extiende la sintaxis estándar del grupo (...)
con un grupo nombrado, (?<name>...)
. Esto permite la extracción por nombre en lugar de tener que contar cuántos grupos tiene.
name_reg = /h(i|ello), my name is (?<name>.*)/i #i means case insensitive
name_input = "Hi, my name is Zaphod Beeblebrox"
match_data = name_reg.match(name_input) #returns either a MatchData object or nil
match_data = name_input.match(name_reg) #works either way
if match_data.nil? #Always check for nil! Common error.
puts "No match"
else
match[0] #=> "Hi, my name is Zaphod Beeblebrox"
match[1] #=> "i" #the first group, (i|ello)
match[2] #=> "Zaphod Beeblebrox"
#Because it was a named group, we can get it by name
match[:name] #=> "Zaphod Beeblebrox"
match["name"] #=> "Zaphod Beeblebrox"
puts "Hello #{match[:name]}!"
end
El índice de la coincidencia se cuenta según el orden de los paréntesis izquierdos (con la expresión regular completa como el primer grupo en el índice 0)
reg = /(((a)b)c)(d)/
match = reg.match 'abcd'
match[0] #=> "abcd"
match[1] #=> "abc"
match[2] #=> "ab"
match[3] #=> "a"
match[4] #=> "d"
= operador ~
if /hay/ =~ 'haystack'
puts "There is hay in the word haystack"
end
Nota: El orden es significativo . Aunque 'haystack' =~ /hay/
es en la mayoría de los casos un equivalente, los efectos secundarios pueden diferir:
- Las cadenas capturadas de los grupos de captura nombrados se asignan a las variables locales solo cuando se llama a
Regexp#=~
(regexp =~ str
); - Como el operando correcto podría ser un objeto arbitrario, para
regexp =~ str
se llamaráRegexp#=~
oString#=~
.
Tenga en cuenta que esto no devuelve un valor verdadero / falso, en su lugar devuelve el índice de la coincidencia si se encuentra, o nil si no se encuentra. Debido a que todos los enteros en ruby son veraces (incluido 0) y nil es falsy, esto funciona. Si desea un valor booleano, use #===
como se muestra en otro ejemplo .
Cuantificadores
Los cuantificadores permiten especificar el recuento de cadenas repetidas.
Cero o uno:
/a?/
Cero o muchos:
/a*/
Uno o muchos:
/a+/
Numero exacto:
/a{2,4}/ # Two, three or four /a{2,}/ # Two or more /a{,4}/ # Less than four (including zero)
Por defecto, los cuantificadores son codiciosos , lo que significa que toman la mayor cantidad de caracteres que pueden mientras hacen una coincidencia. Normalmente esto no se nota:
/(?<site>.*) Stack Exchange/ =~ 'Motor Vehicle Maintenance & Repair Stack Exchange'
El site
grupo de captura nombrado se configurará en "Mantenimiento y reparación de vehículos de motor" como se esperaba. Pero si 'Stack Exchange' es una parte opcional de la cadena (porque podría ser 'Stack Overflow' en su lugar), la solución ingenua no funcionará como se esperaba:
/(?<site>.*)( Stack Exchange)?/
Esta versión aún coincidirá, pero la captura nombrada incluirá 'Intercambio de pila' ya que *
come con avidez esos personajes. La solución es agregar otro signo de interrogación para que el *
perezoso:
/(?<site>.*?)( Stack Exchange)?/
?
Anexando ?
a cualquier cuantificador lo hará perezoso.
Clases de personajes
Describe rangos de símbolos.
Puedes enumerar símbolos explícitamente
/[abc]/ # 'a' or 'b' or 'c'
O utilizar rangos
/[a-z]/ # from 'a' to 'z'
Es posible combinar rangos y símbolos únicos.
/[a-cz]/ # 'a' or 'b' or 'c' or 'z'
El guión inicial ( -
) se trata como un personaje.
/[-a-c]/ # '-' or 'a' or 'b' or 'c'
Las clases pueden ser negativas cuando los símbolos anteriores con ^
/[^a-c]/ # Not 'a', 'b' or 'c'
Hay algunos accesos directos para clases generalizadas y caracteres especiales, además de finales de línea.
^ # Start of line
$ # End of line
\A # Start of string
\Z # End of string, excluding any new line at the end of string
\z # End of string
. # Any single character
\s # Any whitespace character
\S # Any non-whitespace character
\d # Any digit
\D # Any non-digit
\w # Any word character (letter, number, underscore)
\W # Any non-word character
\b # Any word boundary
\n
será entendido simplemente como nueva línea
Para escapar de cualquier personaje reservado, como /
o []
y otros, utilice la barra invertida (barra izquierda)
\\ # => \
\[\] # => []
Expresiones regulares en declaraciones de casos
Puede probar si una cadena coincide con varias expresiones regulares usando una instrucción switch.
Ejemplo
case "Ruby is #1!"
when /\APython/
puts "Boooo."
when /\ARuby/
puts "You are right."
else
puts "Sorry, I didn't understand that."
end
Esto funciona porque se comprueba la igualdad de las declaraciones de casos utilizando el operador ===
, no el operador ==
. Cuando una expresión regular está en el lado izquierdo de una comparación utilizando ===
, probará una cadena para ver si coincide.
Definiendo un Regexp
Un Regexp se puede crear de tres maneras diferentes en Ruby.
utilizando barras:
/ /
utilizando
%r{}
usando
Regex.new
#The following forms are equivalent regexp_slash = /hello/ regexp_bracket = %r{hello} regexp_new = Regexp.new('hello') string_to_match = "hello world!" #All of these will return a truthy value string_to_match =~ regexp_slash # => 0 string_to_match =~ regexp_bracket # => 0 string_to_match =~ regexp_new # => 0
¿partido? - Resultado booleano
Devuelve true
o false
, que indica si la expresión regular coincide o no sin actualizar $~
y otras variables relacionadas. Si el segundo parámetro está presente, especifica la posición en la cadena para comenzar la búsqueda.
/R.../.match?("Ruby") #=> true
/R.../.match?("Ruby", 1) #=> false
/P.../.match?("Ruby") #=> false
Ruby 2.4+
Uso rápido común
Las expresiones regulares a menudo se usan en métodos como parámetros para verificar si hay otras cadenas presentes o para buscar y / o reemplazar cadenas.
A menudo verá lo siguiente:
string = "My not so long string"
string[/so/] # gives so
string[/present/] # gives nil
string[/present/].nil? # gives true
Así que simplemente puedes usar esto como una verificación si una cadena contiene una subcadena
puts "found" if string[/so/]
Más avanzado pero aún breve y rápido: busque un grupo específico utilizando el segundo parámetro, 2 es el segundo en este ejemplo porque la numeración comienza en 1 y no en 0, un grupo es lo que está entre paréntesis.
string[/(n.t).+(l.ng)/, 2] # gives long
También se usa a menudo: buscar y reemplazar con sub
o gsub
, \1
da el primer grupo encontrado, \2
el segundo:
string.gsub(/(n.t).+(l.ng)/, '\1 very \2') # My not very long string
El último resultado se recuerda y se puede utilizar en las siguientes líneas
$2 # gives long