Expresión regular Ruby con nombre de variable

105

¿Es posible crear / usar un patrón de expresión regular en ruby ​​que se base en el valor de un nombre de variable?

Por ejemplo, todos sabemos que podemos hacer lo siguiente con cadenas Ruby:

str = "my string"
str2 = "This is #{str}" # => "This is my string"

Me gustaría hacer lo mismo con las expresiones regulares:

var = "Value"
str = "a test Value"
str.gsub( /#{var}/, 'foo' ) # => "a test foo"

Obviamente, eso no funciona como se indica, solo lo puse allí como ejemplo para mostrar lo que me gustaría hacer. Necesito hacer coincidir expresiones regulares en función del valor del contenido de una variable.

cpjolicoeur
fuente

Respuestas:

184

El código que cree que no funciona, sí:

var = "Value"
str = "a test Value"
p str.gsub( /#{var}/, 'foo' )   # => "a test foo"

Las cosas se ponen más interesantes si var puede contener metacaracteres de expresión regular. Si es así y desea que esos personajes mata hagan lo que suelen hacer en una expresión regular, entonces el mismo gsub funcionará:

var = "Value|a|test"
str = "a test Value"
str.gsub( /#{var}/, 'foo' ) # => "foo foo foo"

Sin embargo, si su cadena de búsqueda contiene metacaracteres y no quiere que se interpreten como metacaracteres, utilice Regexp.escape así:

var = "*This*"
str = "*This* is a string"
p str.gsub( /#{Regexp.escape(var)}/, 'foo' )
# => "foo is a string"

O simplemente asigne a gsub una cadena en lugar de una expresión regular. En MRI> = 1.8.7, gsub tratará un argumento de reemplazo de cadena como una cadena simple, no como una expresión regular:

var = "*This*"
str = "*This* is a string"
p str.gsub(var, 'foo' ) # => "foo is a string"

(Solía ​​ser que un argumento de reemplazo de cadena para gsub se convertía automáticamente en una expresión regular. Sé que era así en 1.6. No recuerdo qué versión introdujo el cambio).

Como se señaló en otras respuestas, puede usar Regexp.new como alternativa a la interpolación:

var = "*This*"
str = "*This* is a string"
p str.gsub(Regexp.new(Regexp.escape(var)), 'foo' )
# => "foo is a string"
Wayne Conrad
fuente
4
La pista en Regexp.escape fue justo lo que no sabía que necesitaba. ¡Gracias!
Jeff Paquette
regxPlayerVariable = '(. *?) =. *? document \ .getElementById (# {pluginPlayeVariable})' en esto apliqué todo lo anterior, pero estos no funcionan.
SSP
1
@SSP Sería bueno explicar el problema en una pregunta aparte.
Wayne Conrad
13

Funciona, pero necesita usar gsub!o asignar el retorno a otra variable

var = "Value"
str = "a test Value"
str.gsub!( /#{var}/, 'foo' )  # Or this: new_str = str.gsub( /#{var}/, 'foo' )
puts str
FMc
fuente
9

si


str.gsub Regexp.new(var), 'foo'
DigitalRoss
fuente
6

Puede usar expresiones regulares a través de variables en ruby:

var = /Value/
str = "a test Value"
str.gsub( /#{var}/, 'foo' )
GeekTantra
fuente
1
No estoy seguro de por qué esto solo tiene votos negativos. Lo probé y funciona, aunque no necesitas las barras de varexpresiones regulares tanto en la variable como en el primer parámetro de gsub.
Tyler Collier
Creo que el objetivo de las barras en gsub era mostrar que una expresión regular puede contener una variable que es en sí misma una expresión regular. La variable no tiene que ser de tipo cadena (y de hecho, la expresión regular es mejor por las razones descritas en la respuesta de Wayne).
mahemoff