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
Chris Bunch
fuente
¿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:

274

Igual que la inserción de cadena.

if goo =~ /#{Regexp.quote(foo)}/
#...
Jonathan Lonowski
fuente
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.

Glenn McDonald
fuente
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.

JasonTrue
fuente
6
Regexp.compile(Regexp.escape(foo))
Markus Jarderot
fuente
3

Utilice Regexp.new:

if goo =~ Regexp.new(foo) # Evaluates to /0.0.0.0/
Jeremy Ruten
fuente
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.

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