如何使用 Groovy 的 replaceFirst 和闭包?

How to use Groovy's replaceFirst with closure?

我是 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]是什么意思? 连名字都不知道要搜

第二,为什么会有"it"的列表? 文档说 replaceFirst()

Replaces the first occurrence of a captured group by the result of a closure call on that text.

"it"不是指"the first occurrence of a captured group"吗?

如果有任何提示和意见,我将不胜感激!

首先,[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')

所以,基本上,闭包内的代码使用该映射作为 查找 tableone 替换为 1two2.

其次,让我们看看regex matcher works:

To find out how many groups are present in the expression, call the groupCount method on a matcher object. The groupCount method returns an int showing the number of capturing groups present in the matcher's pattern. In this example, groupCount would return the number 4, showing that the pattern contains 4 capturing groups.

There is also a special group, group 0, which always represents the entire expression. This group is not included in the total reported by groupCount. Groups beginning with (? are pure, non-capturing groups that do not capture text and do not count towards the group total.

深​​入了解正则表达式内容:

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 重命名为 groupit 就是 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()
}