【问题标题】:Modifying regex matches in replacements在替换中修改正则表达式匹配
【发布时间】:2013-06-17 19:59:20
【问题描述】:

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

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

关于如何做到这一点的任何指示(棘手的部分是我什至不知道如何谷歌)。

编辑

我尝试稍微简化问题以使其更通用,但我也尝试仅在匹配没有出现在引号中的情况下执行此操作。也就是说,我不想匹配引号中的下划线(所以,这里没有匹配:"this_is_a_string"...应该保持原样)。当我第一次发这篇文章时,我可能应该包括这个。

【问题讨论】:

  • 您想查看反向引用。创建两个或多个与第一个相等的正则表达式,然后您可以使用其中一个的反向引用来修改它。
  • @jbrennan 我相信使用原生字符串会更容易,比如 array words = indexOf('-').split; words[1].charAt(1).upperCase; words.join ^^^psuedocode
  • @raam86 我想过这个问题,但我还有一个要求,即只有在引号中没有下划线时才能匹配下划线,所以正则表达式比我展示的要复杂一些。跨度>

标签: ruby regex


【解决方案1】:

你可以在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 个字符。

【讨论】:

  • 啊哈,这很好用。所以我在我的问题中没有提到的是我还必须排除引号之间的实例。你也知道这样做的好方法吗?
  • @jbrennan 您可以先将它们交替匹配,然后按原样返回
  • 你能详细说明这意味着什么吗?我不确定我是否理解。
【解决方案2】:

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-05-25
    • 1970-01-01
    • 2012-05-16
    • 1970-01-01
    • 2013-12-06
    • 2021-04-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多