Inicio / Ruby / Ruby: Lenguaje Elegante y Expresivo / Expresiones Regulares

Expresiones Regulares

Regex en Ruby, match, scan, sub/gsub, grupos, lookahead/lookbehind y validaciones.

Intermedio
🔒 Solo lectura
📖

Estás en modo lectura

Puedes leer toda la lección, pero para marcar progreso, hacer ejercicios y ganar XP necesitas una cuenta Pro.

Desbloquear por $9/mes

Expresiones Regulares en Ruby

Ruby tiene soporte de primera clase para expresiones regulares (Regex), integrado directamente en la sintaxis del lenguaje.


Creación y matching

# Literal
patron = /ruby/i    # i = case insensitive

# Con Regexp.new
patron = Regexp.new("ruby", Regexp::IGNORECASE)

# Match
"Hola Ruby" =~ /ruby/i      # 5 (posición del match)
"Hola Python" =~ /ruby/i    # nil (no hay match)

# match method
resultado = "Hola Ruby 3.3".match(/ruby (\d+\.\d+)/i)
puts resultado[0]    # "Ruby 3.3" (match completo)
puts resultado[1]    # "3.3" (primer grupo)

# match? (solo true/false, más eficiente)
"Hola Ruby".match?(/ruby/i)    # true

# === (usado en case/when)
case "user@example.com"
when /\A[\w.]+@gmail\.com\z/
  "Gmail"
when /\A[\w.]+@[\w.]+\z/
  "Email válido"
else
  "No es email"
end

Variables especiales

"Hola Mundo Ruby" =~ /(\w+) (\w+)/

puts $~       # MatchData: "Hola Mundo"
puts $&       # Match completo: "Hola Mundo"
puts $1       # Grupo 1: "Hola"
puts $2       # Grupo 2: "Mundo"
puts $`       # Antes del match: ""
puts $'       # Después del match: " Ruby"

Patrones comunes

# Caracteres
/[abc]/          # a, b, o c
/[^abc]/         # cualquier cosa excepto a, b, c
/[a-z]/          # letras minúsculas
/[A-Za-z0-9]/    # alfanumérico

# Clases predefinidas
/\d/    # dígito [0-9]
/\D/    # no dígito
/\w/    # word [a-zA-Z0-9_]
/\W/    # no word
/\s/    # whitespace
/\S/    # no whitespace
/./     # cualquier carácter excepto newline

# Cuantificadores
/a*/     # 0 o más
/a+/     # 1 o más
/a?/     # 0 o 1
/a{3}/   # exactamente 3
/a{2,5}/ # entre 2 y 5
/a{3,}/  # 3 o más

# Lazy (no-greedy)
/".*?"/  # match mínimo entre comillas

# Anclas
/\Ahola/    # inicio de string (\A más seguro que ^)
/mundo\z/   # fin de string (\z más seguro que $)
/\bhola\b/  # word boundary

Grupos y capturas

# Grupos con nombre
patron = /(?<año>\d{4})-(?<mes>\d{2})-(?<dia>\d{2})/
match = "2024-03-15".match(patron)

puts match[:año]    # "2024"
puts match[:mes]    # "03"
puts match[:dia]    # "15"

# Grupo sin captura
/(?:https?|ftp):\/\//

# Alternación
/gato|perro/     # "gato" o "perro"

# Backreference
/(\w+) \1/       # palabra repetida: "hola hola"

# Lookahead y lookbehind
/\d+(?= euros)/     # dígitos seguidos de " euros" (positive lookahead)
/\d+(?! euros)/     # dígitos NO seguidos de " euros" (negative lookahead)
/(?<=\$)\d+/        # dígitos precedidos de "$" (positive lookbehind)
/(?<!\$)\d+/        # dígitos NO precedidos de "$" (negative lookbehind)

Métodos con Regex

String#scan

"uno 2 tres 4 cinco 6".scan(/\d+/)
# ["2", "4", "6"]

"Hola Mundo Ruby".scan(/\w+/)
# ["Hola", "Mundo", "Ruby"]

# Con grupos
"2024-03-15 2024-12-25".scan(/(\d{4})-(\d{2})-(\d{2})/)
# [["2024", "03", "15"], ["2024", "12", "25"]]

String#sub y String#gsub

# sub — reemplaza la primera ocurrencia
"Hola Mundo".sub(/mundo/i, "Ruby")     # "Hola Ruby"

# gsub — reemplaza todas
"aaa bbb aaa".gsub(/aaa/, "xxx")       # "xxx bbb xxx"

# Con bloque
"hola mundo".gsub(/\w+/) { |m| m.capitalize }
# "Hola Mundo"

# Con hash
"cat and dog".gsub(/cat|dog/, "cat" => "gato", "dog" => "perro")
# "gato and perro"

# Con backreference
"John Smith".gsub(/(\w+) (\w+)/, '\2, \1')   # "Smith, John"

String#split

"uno, dos, tres".split(/,\s*/)     # ["uno", "dos", "tres"]
"camelCaseWord".split(/(?=[A-Z])/) # ["camel", "Case", "Word"]

Validaciones prácticas

module Validaciones
  # Email
  EMAIL = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i

  # Teléfono (formato español)
  TELEFONO = /\A(\+34)?[6789]\d{8}\z/

  # URL
  URL = /\Ahttps?:\/\/[\w\-.]+(:\d+)?(\/[\w\-._~:\/?#\[\]@!$&'()*+,;=%]*)?\z/

  # Contraseña fuerte
  PASSWORD = /\A(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[\W_]).{8,}\z/

  # IPv4
  IPV4 = /\A(\d{1,3}\.){3}\d{1,3}\z/

  def self.validar(valor, patron, nombre)
    if valor.match?(patron)
      "✅ #{nombre} válido"
    else
      "❌ #{nombre} inválido"
    end
  end
end

puts Validaciones.validar("user@test.com", Validaciones::EMAIL, "Email")
puts Validaciones.validar("+34612345678", Validaciones::TELEFONO, "Teléfono")
puts Validaciones.validar("Ab1!abcd", Validaciones::PASSWORD, "Password")

Flags (modificadores)

/patron/i    # IGNORECASE — insensible a mayúsculas
/patron/m    # MULTILINE — . también matchea newlines
/patron/x    # EXTENDED — permite comentarios y whitespace

# Modo extendido para regex complejas
EMAIL_REGEX = /
  \A
  [\w+\-.]+      # usuario
  @               # arroba
  [a-z\d\-.]+     # dominio
  \.              # punto
  [a-z]+          # TLD
  \z
/xi

Resumen

Método Descripción
=~ Retorna posición del match o nil
match Retorna MatchData
match? Solo true/false
scan Encuentra todas las ocurrencias
sub Reemplaza primera ocurrencia
gsub Reemplaza todas las ocurrencias
split Divide por patrón
(?<name>...) Grupo con nombre
(?=...) Positive lookahead
(?<=...) Positive lookbehind
🔒

Ejercicio práctico disponible

Regex: validación y extracción

Desbloquear ejercicios
// Regex: validación y extracción
// Desbloquea Pro para acceder a este ejercicio
// y ganar +50 XP al completarlo

function ejemplo() {
    // Tu código aquí...
}

¿Te gustó esta lección?

Con Pro puedes marcar progreso, hacer ejercicios, tomar quizzes, ganar XP y obtener tu constancia.

Ver planes desde $9/mes