Expression régulière Ruby utilisant un nom de variable

105

Est-il possible de créer / utiliser un modèle d'expression régulière dans ruby ​​basé sur la valeur d'un nom de variable?

Par exemple, nous savons tous que nous pouvons faire ce qui suit avec des chaînes Ruby:

str = "my string"
str2 = "This is #{str}" # => "This is my string"

J'aimerais faire la même chose avec les expressions régulières:

var = "Value"
str = "a test Value"
str.gsub( /#{var}/, 'foo' ) # => "a test foo"

Évidemment, cela ne fonctionne pas comme indiqué, je ne l'ai mis qu'à titre d'exemple pour montrer ce que j'aimerais faire. J'ai besoin d'une correspondance régulière basée sur la valeur du contenu d'une variable.

cpjolicoeur
la source

Réponses:

184

Le code que vous pensez ne fonctionne pas:

var = "Value"
str = "a test Value"
p str.gsub( /#{var}/, 'foo' )   # => "a test foo"

Les choses deviennent plus intéressantes si var peut contenir des méta-caractères d'expression régulière. Si c'est le cas et que vous voulez que ces mata caractères fassent ce qu'ils font habituellement dans une expression régulière, alors le même gsub fonctionnera:

var = "Value|a|test"
str = "a test Value"
str.gsub( /#{var}/, 'foo' ) # => "foo foo foo"

Cependant, si votre chaîne de recherche contient des métacaractères et que vous ne voulez pas qu'ils soient interprétés comme des métacaractères, utilisez Regexp.escape comme ceci:

var = "*This*"
str = "*This* is a string"
p str.gsub( /#{Regexp.escape(var)}/, 'foo' )
# => "foo is a string"

Ou donnez simplement à gsub une chaîne au lieu d'une expression régulière. Dans MRI> = 1.8.7, gsub traitera un argument de remplacement de chaîne comme une chaîne simple et non comme une expression régulière:

var = "*This*"
str = "*This* is a string"
p str.gsub(var, 'foo' ) # => "foo is a string"

(Auparavant, un argument de remplacement de chaîne dans gsub était automatiquement converti en une expression régulière. Je sais que c'était ainsi dans 1.6. Je ne me souviens pas quelle version a introduit le changement).

Comme indiqué dans d'autres réponses, vous pouvez utiliser Regexp.new comme alternative à l'interpolation:

var = "*This*"
str = "*This* is a string"
p str.gsub(Regexp.new(Regexp.escape(var)), 'foo' )
# => "foo is a string"
Wayne Conrad
la source
4
L'indice sur Regexp.escape était exactement ce dont je ne savais pas avoir besoin. Merci!
Jeff Paquette
regxPlayerVariable = '(. *?) =. *? document \ .getElementById (# {pluginPlayeVariable})' dans ce que j'ai appliqué tout ci-dessus mais ceux-ci ne fonctionnent pas.
SSP
1
@SSP Il serait peut-être bon d'expliquer le problème dans une question distincte.
Wayne Conrad
13

Cela fonctionne, mais vous devez utiliser gsub!ou affecter le retour à une autre variable

var = "Value"
str = "a test Value"
str.gsub!( /#{var}/, 'foo' )  # Or this: new_str = str.gsub( /#{var}/, 'foo' )
puts str
FMc
la source
9

Oui


str.gsub Regexp.new(var), 'foo'
DigitalRoss
la source
6

Vous pouvez utiliser des expressions régulières via des variables dans ruby:

var = /Value/
str = "a test Value"
str.gsub( /#{var}/, 'foo' )
GeekTantra
la source
1
Je ne sais pas pourquoi il n'y a que des votes négatifs. Je l'ai essayé et cela fonctionne, même si vous n'avez pas besoin des barres obliques regex à la fois dans la varvariable et dans le premier paramètre de gsub.
Tyler Collier
Je pense que le but des barres obliques dans gsub était de montrer qu'une regex peut contenir une variable qui est elle-même une regex. La variable n'a pas besoin d'être de type chaîne (et en fait, l'expression régulière est meilleure pour les raisons exposées dans la réponse de Wayne).
mahemoff