0

JavaScript 変数定義を含むテキスト (ページの HTML) があります。

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

のようなルビー正規表現パターンを使用して文字列の内容を一致させ/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

各正規表現に対して複数の置換値を保存できるソリューションを次に示します。

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 に答える
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 に答える