在替换中修改正则表达式匹配

我正在尝试使用正则表达式匹配文本文件中的某些字符串,然后修改找到该模式的所有位置。 这就像搜索和替换,但我试图用已发现的修改版本替换(我确定这有一个名字,但我对它不够熟悉)。

所以我正在寻找与[az]_[az]匹配的字符串(例如, some_string ),我想通过删除下划线并将第二个小some_string词大写来替换它,基本上是camel-casing it( someString )。

关于如何做到这一点的任何指针(棘手的部分是我真的不知道如何甚至谷歌为此)。

编辑

我试图简化这个问题以使其更通用,但我也试图仅在引号中没有匹配的情况下这样做。 也就是说,我不想在引号中匹配下划线(所以,这里不匹配: "this_is_a_string" ……应保持原样)。 当我第一次发帖时,我可能应该包括这个。

你可以使用gsub的回调函数,例如:

 "some_thing_good".gsub(/_([az])/) {|m| m[1].upcase} 

要避免双引号内的字符串,您可以这样做:

 "\"look_at_me\" some_thing_good".gsub(/"[^"]+"|_[az]/) {|m| (m.length>2)? m : m[1].upcase } 

我们的想法是先与之匹配,然后自行更换。 如果我测试匹配长度,我立即知道交替的哪个部分已匹配,因为第二部分仅包含2个字符,第一部分至少包含3个字符。

我认为更好的方法是使用括号来包含您感兴趣的模式。

在您的情况下,我将使用以下正则表达式:

 string.gsub(/(?<=[az])_([az]+)/) {|s| "#{s[1].upcase}#{s[2..-1]}"} 

这个正则表达式可以分为两部分,第一部分要求以有效字符开头的字符串,第二部分后跟“_”和一系列有效字符。

在块代码中,您可以使用Regexp.last_match并返回MatchData,您可以在其中访问括号内的每个模式,例如:

 string.gsub(/(?<=[az])_([az]+)/) do |s| p Regexp.last_match.to_a # this will print all sub-patterns found "#{s[1].upcase}#{s[2..-1]}" # return formatted string end 

正如您所提到的,您对引号内的模式并不感兴趣。 我会在其他内部使用正则表达式。 第一个删除引用的字符串,第二个删除引用的模式:

 string.scan(/(\"[^\"]+\"|([^\"]+))/) do |s| next s[0] unless s[1] # skip quoted data # replace snake case to camel case s[1].gsub(/(?<=[az])_([az]+)/) {|s| "#{s[1].upcase}#{s[2..-1]}"} end