Interpolar una cadena en una expresión regular


160

Necesito sustituir el valor de una cadena en mi expresión regular en Ruby. ¿Hay una forma fácil de hacer esto? Por ejemplo:

foo = "0.0.0.0"
goo = "here is some other stuff 0.0.0.0" 
if goo =~ /value of foo here dynamically/
  puts "success!"
end

¿Estás tratando de ver si foo es una subcadena de goo? No creo que esté claro lo que estás preguntando.
Neall

Si es así, ¡goo.include? (Foo) es suficiente!
glenn mcdonald

1
No, no estaba tratando de ver si foo es una subcadena de goo; También necesitaba hacer algunas capturas, por lo tanto, incluir no funcionó.
Chris Bunch

Respuestas:



125

Tenga Regexp.quoteen cuenta que la respuesta de Jon L. es importante.

if goo =~ /#{Regexp.quote(foo)}/

Si solo haces la versión "obvia":

if goo =~ /#{foo}/

entonces los puntos en el texto de la coincidencia se tratan como comodines regexp y "0.0.0.0"coincidirán "0a0b0c0".

Tenga en cuenta también que si realmente solo desea verificar una coincidencia de subcadena, simplemente puede hacer

if goo.include?(foo)

que no requiere una cita adicional o preocuparse por caracteres especiales.


3
Tenga en cuenta que el reverso (no usar .quote()) también puede ser útil si está buscando construir una expresión regular usando una cadena.
Jesse

"si realmente solo desea verificar una coincidencia de subcadena, simplemente puede hacer if goo.include?(foo)" => Verdadero cuando esté interesado en verificar la existencia. Si está interesado en reemplazar y ya está usando String.gsub, entonces Regexp.quote puede ser su única opción.
Isaac Betesh

Solo para agregar a Jesse en caso de que no sea obvio, esto significa simplemente pasar la cadena de caracteres a los que no necesita escapar Regexp.newo Regexp.compile.
dylankb

Gracias por la útil explicación de por qué podríamos querer usar Regexp.quote
Wylliam Judd

7

Probablemente Regexp.escape(foo)sería un punto de partida, pero ¿hay alguna buena razón por la que no pueda usar la interpolación de expresión más convencional "my stuff #{mysubstitutionvariable}":?

Además, solo puede usar !goo.match(foo).nil?con una cadena literal.




3

Aquí hay otra respuesta limitada pero útil:

Descubrí que puedo insertar fácilmente en una expresión regular sin usar Regexp.quote o Regexp.escape si solo uso comillas simples en mi cadena de entrada: (una coincidencia de dirección IP)

IP_REGEX = '\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}'

my_str = "192.0.89.234 blahblah text 1.2, 1.4" # get the first ssh key 
# replace the ip, for demonstration
my_str.gsub!(/#{IP_REGEX}/,"192.0.2.0") 
puts my_str # "192.0.2.0 blahblah text 1.2, 1.4"

las comillas simples solo interpretan \\ y \ '.

http://en.wikibooks.org/wiki/Ruby_Programming/Strings#Single_quotes

Esto me ayudó cuando necesitaba usar la misma porción larga de una expresión regular varias veces. No es universal, pero se ajusta al ejemplo de la pregunta, creo.


Tengo curiosidad por saber qué se pensará de mi publicación aquí, pero dudo que se vea tan lejos aquí ahora.
Plasmarob el

-2
foo = "0.0.0.0"
goo = "here is some other stuff 0.0.0.0" 

puts "success!" if goo =~ /#{foo}/

2
No, esto dará un "verdadero" erróneo porque "aquí hay algunas otras cosas 070x0! 0", porque los puntos son comodines regexp.
glenn mcdonald
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.