2009-08-01 5 views
7

J'essaie de trouver un moyen de créer dynamiquement un objet regexp à partir d'une chaîne (provenant de la base de données), puis de l'utiliser pour filtrer une autre chaîne. Cet exemple consiste à extraire des données d'un message de validation git, mais en théorie toute expression rationnelle valide peut être présente dans la base de données sous la forme d'une chaîne.Regex dynamique en Ruby

Qu'est-ce qui se passe

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

Ce que je veux arriver

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

Répondre

11

Vous êtes absent qu'une seule chose:

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

backslashs sont des caractères d'échappement dans les chaînes. Si vous voulez un backslash littéral, vous devez le doubler.

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

En règle générale, si vous collé la sortie de vos « lignes brisées », plutôt que l'entrée, vous auriez probablement repéré que le w et s n'ont pas été correctement se sont échappés

+0

Parfait, merci - je savais que je devais faire quelque chose de mal subtilement. – davidsmalley

0

Option 1:

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

Inconvénient: échapper à la main tous les caractères d'échappement connus

Option 2:

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

Inconvénient: Aucun

+0

Pour l'option 2 - l'argument du constructeur est toujours une chaîne car l'expression régulière est extraite de la base de données, ce qui ne fonctionnera pas dans ce scénario. – davidsmalley