Інтерполяція рядка в регулярний вираз


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) достатньо!
glenn mcdonald

1
Ні, я не намагався зрозуміти, чи foo є підрядком goo; Мені теж потрібно було зробити захоплення, отже, включити не вийшло.
Кріс Бунч

Відповіді:



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)" => Істинно, коли вам цікаво перевірити наявність. Якщо ви зацікавлені в заміні і вже використовуєте String.gsub, то Regexp.quote може бути вашим єдиним варіантом.
Ісаак Бетеш

Просто додати до Джессі, якщо це не очевидно, це означає просто передавати рядок символів, до яких вам не потрібно бігти Regexp.newабо Regexp.compile.
dylankb

Дякуємо за корисне пояснення, чому ми можемо захотіти використовувати Regexp.quote
Wylliam Judd

7

Ймовірно, Regexp.escape(foo)це буде відправною точкою, але чи є вагомі причини, що ви не можете використовувати більш звичайний вираз-інтерполяцію:"my stuff #{mysubstitutionvariable}" :?

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




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

Це допомогло мені, коли мені потрібно було використовувати одну і ту ж довгу порцію регулярного виразів кілька разів. Я не вважаю універсальним, але відповідає прикладу питання.


Мені цікаво, що буде думати про мою посаду тут, але я сумніваюся, що це буде видно так далеко зараз тут.
Плазмароб

-2
foo = "0.0.0.0"
goo = "here is some other stuff 0.0.0.0" 

puts "success!" if goo =~ /#{foo}/

2
Ні, це дасть помилкове "справжнє" для "ось ще деякі речі 070x0! 0", тому що точки - це підстановочні символи.
glenn mcdonald
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.