Interpoler une chaîne dans une regex

160

J'ai besoin de remplacer la valeur d'une chaîne dans mon expression régulière dans Ruby. Y a-t-il un moyen facile de faire ceci? Par exemple:

foo = "0.0.0.0"
goo = "here is some other stuff 0.0.0.0" 
if goo =~ /value of foo here dynamically/
  puts "success!"
end
Chris Bunch
la source
Essayez-vous de voir si foo est une sous-chaîne de goo? Je ne pense pas que ce que vous demandez soit clair.
Neall le
Si c'est le cas, goo.include? (Toto) suffit!
glenn mcdonald
1
Non, je n'essayais pas de voir si foo est une sous-chaîne de goo; J'avais également besoin de faire de la capture, donc inclure ne fonctionnait pas.
Chris Bunch

Réponses:

274

Identique à l'insertion de chaîne.

if goo =~ /#{Regexp.quote(foo)}/
#...
Jonathan Lonowski
la source
125

Notez que la Regexp.quotedans la réponse de Jon L. est important!

if goo =~ /#{Regexp.quote(foo)}/

Si vous ne faites que la version "évidente":

if goo =~ /#{foo}/

alors les points de votre texte de correspondance sont traités comme des jokers d'expression régulière et "0.0.0.0"correspondent "0a0b0c0".

Notez également que si vous voulez vraiment simplement vérifier une correspondance de sous-chaîne, vous pouvez simplement faire

if goo.include?(foo)

qui ne nécessite pas de guillemets supplémentaires ni de souci des caractères spéciaux.

glenn mcdonald
la source
3
Notez que l'inverse (ne pas utiliser .quote()) peut également être utile si vous cherchez à construire une expression régulière en utilisant une chaîne.
Jesse
"si vous voulez vraiment simplement vérifier une correspondance de sous-chaîne, vous pouvez simplement faire if goo.include?(foo)" => True lorsque vous souhaitez vérifier l'existence. Si vous souhaitez remplacer et utiliser déjà String.gsub, Regexp.quote peut être votre seule option.
Isaac Betesh
Juste pour ajouter à Jesse au cas où ce ne serait pas évident, cela signifie simplement passer la chaîne de caractères dont vous n'avez pas besoin d'échapper Regexp.newou Regexp.compile.
dylankb
Merci pour l'explication utile des raisons pour lesquelles nous pourrions vouloir utiliser Regexp.quote
Wylliam Judd
7

Probablement Regexp.escape(foo)serait un point de départ, mais est - il une bonne raison pour laquelle vous ne pouvez pas utiliser plus classique expression d'interpolation: "my stuff #{mysubstitutionvariable}"?

En outre, vous pouvez simplement utiliser !goo.match(foo).nil?avec une chaîne littérale.

JasonVrai
la source
6
Regexp.compile(Regexp.escape(foo))
Markus Jarderot
la source
3

Utilisez Regexp.new:

if goo =~ Regexp.new(foo) # Evaluates to /0.0.0.0/
Jeremy Ruten
la source
3

Voici une autre réponse limitée mais utile:

J'ai découvert que je peux facilement insérer dans une regex sans utiliser Regexp.quote ou Regexp.escape si je viens d'utiliser des guillemets simples sur ma chaîne d'entrée: (une adresse IP correspond)

IP_REGEX = '\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}'

my_str = "192.0.89.234 blahblah text 1.2, 1.4" # get the first ssh key 
# replace the ip, for demonstration
my_str.gsub!(/#{IP_REGEX}/,"192.0.2.0") 
puts my_str # "192.0.2.0 blahblah text 1.2, 1.4"

les guillemets simples n'interprètent que \\ et \ '.

http://en.wikibooks.org/wiki/Ruby_Programming/Strings#Single_quotes

Cela m'a aidé lorsque j'ai eu besoin d'utiliser la même portion longue d'une expression régulière plusieurs fois. Pas universel, mais correspond à l'exemple de la question, je crois.

Plasmarob
la source
Je suis curieux de savoir ce que l'on pensera de mon message ici, mais je doute qu'il soit vu aussi loin ici maintenant.
Plasmarob
-2
foo = "0.0.0.0"
goo = "here is some other stuff 0.0.0.0" 

puts "success!" if goo =~ /#{foo}/
Mike Breen
la source
2
Non, cela donnera un "vrai" erroné pour "voici un autre truc 070x0! 0", car les points sont des jokers d'expression régulière.
glenn mcdonald