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

时间:2013-06-17 19:59:20

标签: ruby regex

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

所以我正在寻找与[a-z]_[a-z]匹配的字符串(例如some_string),我希望通过删除下划线并将第二个小写字词大写来替换它,基本上是将它包起来(someString {1}})。

关于如何做到这一点的任何指示(棘手的部分是我真的不知道如何为Google做这个)。

修改

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

2 个答案:

答案 0 :(得分:4)

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

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

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

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

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

答案 1 :(得分:1)

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

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

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

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

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

string.gsub(/(?<=[a-z])_([a-z]+)/) 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(/(?<=[a-z])_([a-z]+)/) {|s| "#{s[1].upcase}#{s[2..-1]}"}
end