Ruby正则表达式 - gsub只捕获组

时间:2014-10-20 01:25:28

标签: ruby regex

我不太清楚我是否理解非捕获组的工作原理。我正在寻找一个正则表达式来产生这个结果:5.214。我认为下面的正则表达式可行,但它正在取代包括非捕获组在内的所有内容。如何编写正则表达式才能替换捕获组?

"5,214".gsub(/(?:\d)(,)(?:\d)/, '.')
# => ".14"

我想要的结果:

"5,214".gsub(some_regex)
#=> "5.214

6 个答案:

答案 0 :(得分:19)

你不能。 gsub取代整场比赛;它对捕获的组没有任何作用。无论这些群体是否被捕获都没有任何区别。

为了达到效果,你需要使用lookbehind和lookahead。

"5,214".gsub(/(?<=\d),(?=\d)/, '.')

答案 1 :(得分:9)

非捕获组仍然消耗比赛
使用
 "5,214".gsub(/(\d+)(,)(\d+)/, '\1.\3')

"5,214".gsub(/(?<=\d+)(,)(?=\d+)/, '.')

答案 2 :(得分:8)

gsub替换正则表达式引擎生成的整个匹配项。

RTFM,不保留捕获/非捕获组构造。但是,您可以使用lookaround断言,这些断言不会消耗&#34;字符串上的任何字符。

"5,214".gsub(/\d\K,(?=\d)/, '.')

说明: \K转义序列重置报告的匹配的起点,不再包含任何以前消费的字符。话虽如此,我们然后查找并匹配逗号,而Positive Lookahead断言数字跟随。

答案 3 :(得分:4)

也可以在块版本中使用Regexp.last_match(也可以通过$~使用)来访问完整的MatchData

"5,214".gsub(/(\d),(\d)/) { |_|
    match = Regexp.last_match

    "#{match[1]}.#{match[2]}"
}

这可以更好地扩展到涉及更多的用例。

Nota bene,来自Ruby文档:

  

:: last_match在进行模式匹配的方法的线程和方法范围内是本地的。

答案 4 :(得分:0)

我对红宝石一无所知。

但是我在tutorial

中看到的

gsub意味着替换, 模式应为/(?<=\d+),(?=\d+)/,只需用逗号替换逗号即可 或者,使用捕获/(\d+),(\d+)/将字符串替换为"\1.\2"

答案 5 :(得分:0)

您不需要正则表达式来实现您的需求:

'1,200.00'.tr('.','!').tr(',','.').tr('!', ',')

  • 期间变为刘海(1,200!00
  • 逗号成为句点(1.200!00
  • Bangs成为逗号(1.200,00