我有一些包含JavaScript变量定义的文本(页面的HTML):
var FOREGROUND_COLOR = '#ffffff';
var BACKGROUND_COLOR = '#aaaaaa';
var BORDER_COLOR = '#000000';
我希望使用像/var BACKGROUND_COLOR = '(#.*?)';/
这样的ruby regexp模式匹配字符串内容,并用替换值(#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';
的形式出现 - 它可能是CSS规则,或URL或其他任意模式。如果我有值X, Y and Z
和模式/The letters of the day are (.*?), Cookie Monster/
以及包含
<p>Welcome to Sesame Street!</p>
<p>The letters of the day are Q, J and L, Cookie Monster. Do you like them?</p>
我的操作后内容应为
<p>Welcome to Sesame Street!</p>
<p>The letters of the day are X, Y and Z, Cookie Monster. Do you like them?</p>
我不认为7月11日之前的答案提供了一个通用的解决方案,尽管他们可能会回答我提出的问题。谢谢。
答案 0 :(得分:1)
的脚本:强> 的
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';
测试代码here。
答案 1 :(得分:1)
这是一个允许您为每个正则表达式存储多个替换值的解决方案:
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