用值替换捕获,然后返回整个匹配的模式

我有一些包含JavaScript变量定义的文本(页面的HTML):

var FOREGROUND_COLOR = '#ffffff'; var BACKGROUND_COLOR = '#aaaaaa'; var BORDER_COLOR = '#000000'; 

我想使用ruby regexp模式匹配字符串内容,如/var BACKGROUND_COLOR = '(#.*?)';/并用替换值( #bbbbbb )替换捕获,但随后返回整个原始模式值被替换,以便新内容

 var FOREGROUND_COLOR = '#ffffff'; var BACKGROUND_COLOR = '#bbbbbb'; var BORDER_COLOR = '#000000'; 

主要约束是模式在外部文件中定义,替换值来自数据库,内容(带有javascript的HTML页面和我想要更改的其他值)在运行时不受我的控制。 因此,当定义模式时,我不知道替换,并且当定义替换时,我不知道模式。 因此,我需要假设模式和值都给出。

简单的ruby gsub不起作用:

 contents.gsub(pattern, replacement) => var FOREGROUND_COLOR = '#ffffff'; #bbbbbb // this is the problem with simple gsub var BORDER_COLOR = '#000000'; 

但看起来我可以使用反向引用( \1 )来使用块语法。 但我宁愿不必更改我的模式,因为它们已经很复杂(这是一个简化的案例,并且regexp是处理模式变化所必需的)。 我可以破解并使它工作,但这似乎并不明智。

我怎样才能在Ruby中高效地完成这项工作?

附加澄清(为什么还没有接受答案)我事先知道模式,但它并不总是以var SOMETHING = '#COLOR_VALUE';的formsvar SOMETHING = '#COLOR_VALUE'; – 它可能是CSS规则,或URL或其他任意模式。 如果我有一个值X, Y and Z和一个模式/The letters of the day are (.*?), Cookie Monster/和包含的内容

 

Welcome to Sesame Street!

The letters of the day are Q, J and L, Cookie Monster. Do you like them?

我的操作后应该是内容

 

Welcome to Sesame Street!

The letters of the day are X, Y and Z, Cookie Monster. Do you like them?

我不认为7月11日的答案提供了通用的解决方案,尽管他们可能会回答我提出的问题。 谢谢。

这是一个允许您为每个正则表达式存储多个替换值的解决方案:

 JS = %Q{ var FOREGROUND_COLOR = '#ffffff'; var BACKGROUND_COLOR = '#aaaaaa'; var BORDER_COLOR = '#000000'; } # String regexes from DB mapped to array of replacement values # First array entry [0] matched the first regex capture \1 FIND_REPLACE = { "var BACKGROUND_COLOR = '(#.*?)';" => ['#bbbbbb'] } def replace_all( str, find_replace ) str.dup.tap do |result| find_replace.each do |re,replacements| result.gsub! Regexp.new(re) do matches = $~ matches[0].tap do |result| replacements.each.with_index do |replacement,i| found = matches[i+1] puts "Replacing #{found} with #{replacement}" result[found] = replacement end end end end end end puts replace_all( JS, FIND_REPLACE ) #=> Replacing #aaaaaa with #bbbbbb #=> #=> var FOREGROUND_COLOR = '#ffffff'; #=> var BACKGROUND_COLOR = '#bbbbbb'; #=> var BORDER_COLOR = '#000000'; 

这不是一个理想的答案,因为如果此传递上的先前替换的结果创建的内容与稍后匹配的文本相同,则行result[found] = replacement可能做错了。 例如:

 # Should output "dogs = emus" puts replace_all "cats = dogs", "(\\w+) = (\\w+)" => ["dogs","emus"] #=> Replacing cats with dogs #=> Replacing dogs with emus #=> emus = dogs # Should output "foo = bar" puts replace_all "foo = foo", "foo = (\\w+)" => ["bar"] #=> Replacing foo with bar #=> bar = foo 

脚本:

 contents = 'var FOREGROUND_COLOR = \'#ffffff\'; var BACKGROUND_COLOR = \'#aaaaaa\'; var BORDER_COLOR = \'#000000\';' pattern = '(?<=(var BACKGROUND_COLOR = \'))(#[a-zA-Z\d]+)(?=(\';))' replacement = '#bbbbbb' contents = contents.sub(/#{pattern}/m, replacement) puts contents; puts "\n" puts $1+$2+$3; 

输出:

 var FOREGROUND_COLOR = '#ffffff'; var BACKGROUND_COLOR = '#bbbbbb'; var BORDER_COLOR = '#000000'; var BACKGROUND_COLOR = '#aaaaaa'; 

在这里测试代码。