0

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

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

我想使用 ruby​​ 正则表达式模式匹配字符串内容/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)来使用块语法。但我宁愿不必更改我的模式,因为它们已经很复杂(这是一个简化的情况,正则表达式是处理模式变化所必需的)。我可以破解并使其工作,但这似乎并不明智。

如何在 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 日之前的答案提供了一个通用的解决方案,尽管他们可能会回答我提出的问题。谢谢你。

4

2 回答 2

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';

在这里测试代码。

于 2012-07-03T13:46:50.270 回答
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
于 2012-07-03T15:00:40.010 回答