Quiero reemplazar el contenido (o eliminarlo) que no coincide con mi filtro. Creo que la descripción perfecta sería un subtítulo opuesto. No puedo encontrar nada similar en los documentos, y no estoy seguro de cómo invertir la expresión regular, pero creo que un método probablemente sería más conveniente.

Un ejemplo de cómo funcionaría (acabo de cambiar las palabras para que quede más claro)

"bird.cats.dogs".opposite_sub(/(dogs|cats)\.(dogs|cats)/, '') 
#"cats.dogs"

Espero que sea bastante fácil de entender. Gracias por adelantado.

2
hcarreras 26 ene. 2016 a las 18:24

3 respuestas

La mejor respuesta

String#[] puede tomar una expresión regular como parámetro:

▶ "bird.cats.dogs"[/(dogs|cats)\.(dogs|cats)/]
#⇒ "cats.dogs"

Para múltiples coincidencias, se puede usar String#scan:

▶ "bird.cats.dogs.bird.cats.dogs".scan /(?:dogs|cats)\.(?:dogs|cats)/
#⇒ ["cats.dogs", "cats.dogs"]
4
the Tin Man 26 ene. 2016 a las 18:13

Entonces, ¿quieres extraer la parte que coincida con tu expresión regular?

Puede utilizar String#slice, por ejemplo:

"bird.cats.dogs".slice(/(dogs|cats)\.(dogs|cats)/)
#=> "cats.dogs"

Y String#[] sí lo mismo.

"bird.cats.dogs"[/(dogs|cats)\.(dogs|cats)/]
#=> "cats.dogs"
3
molf 26 ene. 2016 a las 15:28

No puede tener una sola cadena de reemplazo porque la parte de la cadena que coincide con la expresión regular podría no estar al principio o al final de la cadena, en cuyo caso no está claro si la cadena de reemplazo debe preceder o seguir a la cadena coincidente. Por lo tanto, escribí lo siguiente con dos cadenas de reemplazo, una para pre-match y la otra para post_match. Hice de este un método de la clase String, ya que eso es lo que ha pedido (aunque le he dado al método un nombre menos perfecto :-))

class String
  def replace_non_matching(regex, replace_before, replace_after)
    first, match, last = partition(regex)
    replace_before + match + replace_after
  end
end

r = /(dogs|cats)\.(dogs|cats)/

"birds.cats.dogs.pigs".replace_non_matching(r, "", "")
  #=> "cats.dogs"

"birds.cats.dogs".replace_non_matching(r, "snakes.", ".hens")
  #=> "snakes.cats.dogs.hens" 

"birds.cats.dogs.mice.cats.dogs.bats".replace_non_matching(r, "snakes.", ".hens")
  #=> "snakes.cats.dogs.hens" 

Con respecto al último ejemplo, el método podría modificarse para reemplazar "birds.", ".mice." y ".bats", pero en ese caso se necesitarían tres cadenas de reemplazo. En general, determinar de antemano el número de cadenas de reemplazo necesarias podría ser problemático.

1
Cary Swoveland 26 ene. 2016 a las 19:50