正则表达式 – 如何使用Groovy的replaceFirst与闭包?

我是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]是什么意思?
我甚至不知道要搜索它的名字.

第二,为什么有“它”列表?
doc说replaceFirst()

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

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

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

最佳答案 首先,[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')

因此,基本上,闭包内的代码使用该映射作为查找表,将1替换为2,将2替换为2.

其次,让我们看看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]

所以我们可以更清楚地重写代码,按组重命名(它只是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()
}
点赞