2012-11-08 47 views
0

的部分我有一個紅寶石可變的大型文件,它遵循像這樣一個共同的模式:紅寶石查找和替換字符串

// ... 

// comment 
$myuser['bla'] = 'bla'; 

// comment 
$myuser['bla2'] = 'bla2'; 

// ... 

我試圖給出一個「關鍵」取代「價值」

這取代了整個字符串,我該如何解決它?我認爲另一種方法是分兩步進行,第一步是在引號內查找值,然後執行字符串替換,最好的方法是什麼?

def keyvalr(content, key, value) 
    return content.gsub(/\$bla\[\'#{key}\'\]\s+\=\s+\'(.*)\'/) {|m| value } 
end 
+0

你的輸入文件是一個php文件嗎? – willoller

+0

在這種情況下,這是肯定的 – user391986

+0

我假設你需要保留評論和其他信息,所以在文件上運行php來做替換不會是一個選項。 – willoller

回答

1

.*是貪婪的,消耗盡可能(一切直到最後')。使.一個[^']然後它不可能超過第一個關閉'

/(\$bla\[\'#{key}\'\]\s+\=\s+\')[^']*(\')/ 

我還添加了括號來捕獲除了要替換的值之外的所有內容。第一組參數將對應於\1,第二組參數將對應\2。所以你更換的這個與比賽:

"\1yournewvaluehere\2" 
+0

感謝keyvalr(內容「bla」,「newbla」)的問題替換了整個行「$ myuser ['bla'] ='bla';」以「newbla」 – user391986

+0

哦對。我不知道正確的ruby語法,但是你可以創建這樣的捕獲組:'/(\ $ bla \ [\'#{key} \'\] \ s + \ = \ s + \'=) [^'] *(\')/',然後用'「\ 1newbla \ 2」'替換。 '\ 1'和'\ 2'將包含兩組括號中匹配的內容。 –

0

我會使用類似:

text = %q{ 
// ... 

// comment 
$myuser['bla'] = 'bla'; 

// comment 
$myuser['bla2'] = 'bla2'; 

// ... 
} 

from_to = { 
    'bla' => 'foo', 
    'bla2' => 'bar' 
} 

puts text.gsub(/\['([^']+)'\] = '([^']+)'/) { |t| 
    key, val = t.scan(/'([^']+)'/).flatten 
    "['%s'] = '%s'" % [ key, from_to[key] ] 
} 

,輸出:

// ... 

// comment 
$myuser['bla'] = 'foo'; 

// comment 
$myuser['bla2'] = 'bar'; 

// ... 

這是它如何工作的:

如果我這樣做:

puts text.gsub(/\['([^']+)'\] = '([^']+)'/) { |t| 
    puts t 
} 

我看到:

['bla'] = 'bla' 
['bla2'] = 'bla2' 

然後我嘗試:

"['bla'] = 'bla'".scan(/'([^']+)'/).flatten 
=> ["bla", "bla"] 

這給了我一把鑰匙,「值」對,所以我可以使用哈希來查找替換值。

gsub塊中粘貼它意味着任何匹配被替換爲我的塊返回值,所以我創建了一個字符串來替換「hit」,並讓gsub做它的「thang」。

我不是使用長正則表達式的信徒。我不得不維護太多試圖使用複雜模式的代碼,並且出錯,並且無法完成100%的時間。它們非常強大,但維護代碼比開發代碼更困難/更糟糕,所以我儘量保留用勺子大小寫的模式,憐憫那些跟着我維護代碼的人。