2009-08-01 22 views
7

Sto cercando di trovare un modo per farmi creare dinamicamente un oggetto regexp da una stringa (preso dal database) e quindi usarlo per filtrare un'altra stringa. Questo esempio serve per estrarre i dati da un messaggio di commit git, ma in teoria qualsiasi espressione regexp valida potrebbe essere presente nel database come stringa.Dynamic Regex in Ruby

Cosa succede

>> 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 

Quello che voglio che accada

>> 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" 

risposta

11

Stai manca solo una cosa:

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

barre inverse sono caratteri di escape nelle stringhe. Se vuoi un backslash letterale devi raddoppiarlo.

>> 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 " 

In genere, se avessi incollato l'uscita dalle vostre linee "spezzate", piuttosto che solo l'ingresso, si sarebbe probabilmente hai trovato che il w e s non erano sfuggiti correttamente

+0

Perfetto, grazie - ho capito che dovevo fare qualcosa di sottilmente sbagliato. – davidsmalley

0

Opzione 1:

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

Svantaggio: escape manualmente tutti i caratteri di escape conosciuti

Opzione 2:

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

Svantaggi: Nessuno

+0

Per l'opzione 2 - l'argomento per il costruttore è sempre stringa perché l'espressione regolare viene estratta dal database in modo che non funzioni in questo scenario. – davidsmalley