【问题标题】:How to use Groovy's replaceFirst with closure?如何使用 Groovy 的 replaceFirst 和闭包?
【发布时间】:2015-03-25 09:11:02
【问题描述】:

我是 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()

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

“它”不是指“第一次出现的捕获组”吗?

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

【问题讨论】:

    标签: regex groovy closures


    【解决方案1】:

    首先,[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 重命名为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()
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-12-30
      • 2011-03-15
      • 2021-10-23
      • 2016-02-08
      • 2022-07-01
      • 2014-04-02
      • 2011-01-02
      • 1970-01-01
      相关资源
      最近更新 更多