如何使用Groovy的replaceFirst封闭?

时间:2015-03-25 09:11:02

标签: regex groovy closures

我是Groovy的新手,对replaceFirst有关闭问题有疑问。

groovy-jdk API doc给我举例......

assert "hellO world" == "hello world".replaceFirst("(o)") { it[0].toUpperCase() } // first match
assert "hellO wOrld" == "hello world".replaceAll("(o)") { it[0].toUpperCase() }   // all matches

assert '1-FISH, two fish' == "one fish, two fish".replaceFirst(/([a-z]{3})\s([a-z]{4})/) { [one:1, two:2][it[1]] + '-' + it[2].toUpperCase() }
assert '1-FISH, 2-FISH' == "one fish, two fish".replaceAll(/([a-z]{3})\s([a-z]{4})/) { [one:1, two:2][it[1]] + '-' + it[2].toUpperCase() }

前两个例子非常简单,但我无法理解其余的例子。

首先,[one:1, two:2]是什么意思? 我甚至不知道要搜索它的名字。

其次,为什么有“它”列表? 该文档说replaceFirst()

  

用该文本的闭包调用结果替换第一次出现的捕获组。

“它”不是指“捕获组首次出现”吗?

我将不胜感激任何提示和评论!

1 个答案:

答案 0 :(得分:2)

首先,[one:1, two:2]是地图:

assert [one:1, two:2] instanceof java.util.Map
assert 1 == [one:1, two:2]['one']
assert 2 == [one:1, two:2]['two']
assert 1 == [one:1, two:2].get('one')
assert 2 == [one:1, two:2].get('two')

因此,基本上,闭包内的代码使用该地图作为查找表,将one替换为1,将two替换为2 }。

其次,让我们看看regex matcher works

的方式
  

要查明表达式中有多少个组,请调用   匹配器对象上的groupCount方法。 groupCount方法返回   一个int,显示匹配器中存在的捕获组的数量   图案。在此示例中,groupCount将返回数字4,   显示该模式包含4个捕获组。

     

还有一个特殊组,即组0,它始终代表整个表达式。该组未包括在报告的总数中   groupCount。以?开头的组是纯粹的非捕获组   不捕获文本而不计入小组总数。

深入研究正则表达式:

def m = 'one fish, two fish' =~ /([a-z]{3})\s([a-z]{4})/
assert m instanceof java.util.regex.Matcher
m.each { group ->
    println group
}

这会产生:

[one fish, one, fish] // only this first match for "replaceFirst"
[two fish, two, fish]

因此,我们可以更清楚地重写代码it group it只需default name of the argument in a single argument closure}:

assert '1-FISH, two fish' == "one fish, two fish".replaceFirst(/([a-z]{3})\s([a-z]{4})/) { group ->
    [one:1, two:2][group[1]] + '-' + group[2].toUpperCase() 
}
assert '1-FISH, 2-FISH' == "one fish, two fish".replaceAll(/([a-z]{3})\s([a-z]{4})/) { group ->
    [one:1, two:2][group[1]] + '-' + group[2].toUpperCase()
}