Интерполяция строки в регулярное выражение

160

Мне нужно подставить значение строки в мое регулярное выражение в Ruby. Есть простой способ сделать это? Например:

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
Крис Банч
источник
Вы пытаетесь увидеть, является ли foo подстрокой goo? Я не думаю, что понятно, о чем ты спрашиваешь.
Не
Если так, то goo.include? (Foo) достаточно!
Гленн Макдональд
1
Нет, я не пытался увидеть, является ли foo подстрокой goo; Мне также нужно было сделать несколько снимков, поэтому включить не получилось.
Крис Банч

Ответы:

274

То же, что и вставка строки.

if goo =~ /#{Regexp.quote(foo)}/
#...
Джонатан Лоновски
источник
125

Обратите внимание , что Regexp.quoteв ответ Джон Лоэнгрина важно!

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

Если вы просто делаете «очевидную» версию:

if goo =~ /#{foo}/

тогда точки в вашем тексте совпадения рассматриваются как подстановочные знаки регулярного выражения и "0.0.0.0"будут совпадать "0a0b0c0".

Также обратите внимание, что если вы действительно хотите проверить соответствие подстроки, вы можете просто сделать

if goo.include?(foo)

который не требует дополнительного цитирования или беспокойства о специальных символах.

Гленн Макдональд
источник
3
Обратите внимание, что обратное (не использование .quote()) также может быть полезно, если вы хотите построить регулярное выражение, используя строку.
Джесси
«если вы действительно хотите проверить соответствие подстроки, вы можете просто сделать if goo.include?(foo)» => True, если вы заинтересованы в проверке существования. Если вы заинтересованы в замене и уже используете String.gsub, то Regexp.quote может быть вашим единственным вариантом.
Исаак Бетеш
Просто добавить к Джесси в случае, если это не очевидно, это означает просто передать строку символов, в которую вы не нуждаетесь, чтобы избежать Regexp.newили Regexp.compile.
Диланкб
Спасибо за полезное объяснение того, почему мы можем захотеть использовать Regexp.quote
Wylliam Judd
7

Вероятно , Regexp.escape(foo)было бы отправной точкой, но есть хорошая причина , вы не можете использовать более обычное выражение-интерполяции: "my stuff #{mysubstitutionvariable}"?

Кроме того, вы можете просто использовать !goo.match(foo).nil?с литеральной строкой.

JasonTrue
источник
6
Regexp.compile(Regexp.escape(foo))
Маркус Жардеро
источник
3

Используйте Regexp.new:

if goo =~ Regexp.new(foo) # Evaluates to /0.0.0.0/
Джереми Рутен
источник
3

Вот ограниченный, но полезный другой ответ:

Я обнаружил, что могу легко вставить в регулярное выражение, не используя Regexp.quote или Regexp.escape, если я просто использовал одинарные кавычки в моей входной строке: (соответствие IP-адреса)

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"

одиночные кавычки интерпретируют только \\ и \ '.

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

Это помогло мне, когда мне нужно было использовать одну и ту же длинную часть регулярного выражения несколько раз. Не универсальный, но подходит под вопрос вопроса, я считаю.

Plasmarob
источник
Мне любопытно, что подумают о моем посте здесь, но я сомневаюсь, что это будет видно здесь и сейчас.
Plasmarob
-2
foo = "0.0.0.0"
goo = "here is some other stuff 0.0.0.0" 

puts "success!" if goo =~ /#{foo}/
Майк Брин
источник
2
Нет, это даст ошибочное «истину», поскольку «здесь есть другие вещи 070x0! 0», потому что точки являются регулярными символами регулярного выражения.
Гленн Макдональд