2009-08-01 16 views
7

Estoy tratando de encontrar una forma de permitirme crear dinámicamente un objeto regexp a partir de una cadena (tomada de la base de datos) y luego usar eso para filtrar otra cadena. Este ejemplo es para extraer datos de un mensaje de confirmación de git, pero en teoría cualquier expresión regular válida podría estar presente en la base de datos como una cadena.Dynamic Regex en Ruby

¿Qué ocurre

>> string = "[ALERT] Project: Revision ...123456 committed by Me <[email protected]>\n on 2009- 07-28 21:21:47\n\n Fixed typo\n" 
>> r = Regexp.new("[A-Za-z]+: Revision ...[\w]+ committed by [A-Za-z\s]+") 
>> string[r] 
=> nil 

Lo que quiero que suceda

>> string = "[ALERT] Project: Revision ...123456 committed by Me <[email protected]>\n on 2009- 07-28 21:21:47\n\n Fixed typo\n" 
>> string[/[A-Za-z]+: Revision ...[\w]+ committed by [A-Za-z\s]+/] 
=> "Project: Revision 123456 committed by Me" 

Respuesta

11

Sólo te falta una cosa:

>> Regexp.new "\w" 
=> /w/ 
>> Regexp.new "\\w" 
=> /\w/ 

Las barras invertidas son caracteres de escape en cadenas. Si quieres una barra invertida literal, debes duplicarla.

>> string = "[ALERT] Project: Revision ...123456 committed by Me <[email protected]>\n on 2009- 07-28 21:21:47\n\n Fixed typo\n" 
=> "[ALERT] Project: Revision ...123456 committed by Me <[email protected]>\n on 2009- 07-28 21:21:47\n\n Fixed typo\n" 
>> r = Regexp.new("[A-Za-z]+: Revision ...[\\w]+ committed by [A-Za-z\\s]+") 
=> /[A-Za-z]+: Revision ...[\w]+ committed by [A-Za-z\s]+/ 
>> string[r] 
=> "Project: Revision ...123456 committed by Me " 

Por lo general, si lo ha pegado la salida de sus líneas "roto", en lugar de sólo la entrada, lo que probablemente ha detectado que el w y s no se escaparon adecuadamente

+0

perfecto, gracias - Yo sabía que tenía que estar haciendo algo mal sutilmente. – davidsmalley

0

Opción 1:

# Escape the slashes: 
r = Regexp.new("[A-Za-z]+: Revision ...[\\w]+ committed by [A-Za-z\\s]+") 

Desventaja: Escape de forma manual todos los caracteres de escape conocidos

Opción 2:

# Use slashes in constructor 
r = Regexp.new(/[A-Za-z]+: Revision ...[\w]+ committed by [A-Za-z\s]+/) 

Desventaja: Ninguno

+0

Para la opción 2: el argumento para el constructor es siempre una cadena porque la expresión regular se extrae de la base de datos para que no funcione en este escenario. – davidsmalley