web-dev-qa-db-fra.com

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

Est-il possible de créer/utiliser un motif d'expression régulière dans Ruby qui est basé sur la valeur d'un nom de variable?

Par exemple, nous savons tous que nous pouvons effectuer les opérations suivantes avec les 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 le cite seulement à titre d'exemple pour montrer ce que j'aimerais faire. J'ai besoin de faire une correspondance rationnelle en fonction de la valeur du contenu d'une variable.

95
cpjolicoeur

Le code que vous pensez ne fonctionne pas, fait:

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 matacaracters 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 les interpréter en tant que métacaractères, utilisez alors 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. En IRM> = 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 de gsub était automatiquement converti en une expression régulière. Je sais que c'était le cas dans la version 1.6. Je ne me souviens pas de la version qui a introduit la modification).

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"
170
Wayne Conrad

Cela fonctionne, mais vous devez utiliser gsub! ou assigner 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
13
FMc

Oui


str.gsub Regexp.new(var), 'foo'
9
DigitalRoss

Vous pouvez utiliser des expressions régulières via des variables en Ruby:

var = /Value/
str = "a test Value"
str.gsub( /#{var}/, 'foo' )
4
GeekTantra
str.gsub( Regex.new("#{var}"), 'foo' )
3
DNNX