【问题标题】:Extract numeric data from string in groovy从groovy中的字符串中提取数字数据
【发布时间】:2020-12-01 01:54:47
【问题描述】:

我得到一个可以包含文本和数字数据的字符串:

例子:

“100 磅” “我认为 173 磅” “73 磅。”

我正在寻找一种干净的方法来仅从这些字符串中提取数字数据。

这是我目前正在做的以剥离响应:

def stripResponse(String response) {
    if(response) {
        def toRemove = ["lbs.", "lbs", "pounds.", "pounds", " "]
        def toMod = response
        for(remove in toRemove) {
            toMod = toMod?.replaceAll(remove, "")
        }
        return toMod
    }
}

【问题讨论】:

    标签: string groovy


    【解决方案1】:

    您可以使用findAll 然后将结果转换为整数:

    def extractInts( String input ) {
      input.findAll( /\d+/ )*.toInteger()
    }
    
    assert extractInts( "100 pounds is 23"  ) == [ 100, 23 ]
    assert extractInts( "I think 173 lbs"   ) == [ 173 ]
    assert extractInts( "73 lbs."           ) == [ 73 ]
    assert extractInts( "No numbers here"   ) == []
    assert extractInts( "23.5 only ints"    ) == [ 23, 5 ]
    assert extractInts( "positive only -13" ) == [ 13 ]
    

    如果您需要小数和负数,您可以使用更复杂的正则表达式:

    def extractInts( String input ) {
      input.findAll( /-?\d+\.\d*|-?\d*\.\d+|-?\d+/ )*.toDouble()
    }
    
    assert extractInts( "100 pounds is 23"   ) == [ 100, 23 ]
    assert extractInts( "I think 173 lbs"    ) == [ 173 ]
    assert extractInts( "73 lbs."            ) == [ 73 ]
    assert extractInts( "No numbers here"    ) == []
    assert extractInts( "23.5 handles float" ) == [ 23.5 ]
    assert extractInts( "and negatives -13"  ) == [ -13 ]
    

    【讨论】:

    • 我最终根据上面的建议实施的解决方案,我只想获取第一个数字(如果有多个我会使响应无效)。谢谢@tim_yates! def extractNumericData(String response) { if(response) { def numberList = response.findAll( /[0-9]+.[0-9]*|[0-9]*.[0-9]+|[0-9]+/ ) if(numberList.size() == 1) { return numberList.get(0) as BigDecimal } else { return -1 } } }
    • 出于某种原因,我得到了这个:java.lang.UnsupportedOperationException: spread not yet supported in input.findAll(\d+)*.toInteger()。 ---- 它在Jenkins 上说它已解决。
    【解决方案2】:

    把它放在这里给同样需要它的人。

    我不需要创建新问题,而是需要一个字符串中的一个数字。

    我用正则表达式做到了这一点。

    def extractInt( String input ) {
      return input.replaceAll("[^0-9]", "")
    }
    

    输入可以是this.may.have.number4.com 并返回4

    我从上面的答案中收到错误(可能是由于我的 Jenkins 版本)-出于某种原因,我得到了这个:java.lang.UnsupportedOperationException: spread not yet supported in input.findAll(\d+)*.toInteger() ---- 它在Jenkins 上说它已解决。

    希望这会有所帮助。

    【讨论】:

    • 赞成,因为虽然它没有回答确切的问题,但提供了一个很好的简单子案例
    • replaceAll 并用空格替换,如果你想解析多个整数。例如input.replaceAll("[^0-9][^0-9]*", " ")
    【解决方案3】:

    通过metaClass添加下面的方法numbersFilter后,可以如下调用:

    assert " i am a positive number 14".numbersFilter() == [ 14 ]
    assert " we 12 are 20.3propaged 10.7".numbersFilter() == [ 12,20.3,10.7 ]
    assert " we 12 a20.3p 10.7 ,but you can select one".numbersFilter(0) == 12
    assert " we 12 a 20.3 pr 10.7 ,select one by index".numbersFilter(1) == 20.3
    

    将此代码添加为 BootStrap

    String.metaClass.numbersFilter={index=-1->
                def tmp=[];
                tmp=delegate.findAll( /-?\d+\.\d*|-?\d*\.\d+|-?\d+/ )*.toDouble()
                if(index<=-1){
                    return tmp;
                }else{
                    if(tmp.size()>index){
                        return tmp[index];
                    }else{
                       return tmp.last();
                    }
                }
    
    }
    

    【讨论】:

      【解决方案4】:

      由于 input.findAll( /\d+/ )*.toInteger() 不适用于 Jenkins。您可以改用它。

      def packageVersion = "The package number is 9.2.5847.1275"
      def nextversion=packageVersion.findAll( /\d+/ ).collect{ "$it".toInteger() }
      nextversion.add(nextversion.pop()+1)
      nextversion = nextversion.join('.')
      Result: 9.2.5847.1276
      

      【讨论】:

        【解决方案5】:

        另一种替代解决方案,没有 RegEx。它将字符串解析为标记并将它们转换为数字列表或空值。删除空值,最后只考虑第一个条目(根据需要)。

        def extractNumericData(String response) {
            response.split(' ')
                .collect { it.isFloat() ? Float.parseFloat(it) : null }
                .findAll { it }
                .first()
        }
        
        assert 100 == extractNumericData("100 pounds")
        assert 173 == extractNumericData("I think 173 lbs")
        assert 73 == extractNumericData("73 lbs.")
        

        【讨论】:

          【解决方案6】:

          当逐行解析 String.contains 和 String.replaceAll 时(用空格替换所有非数字字符序列) 然后 String.split() 组合很有用,像这样:

          if (line.contains("RESULT:")) {
              l = line.replaceAll("[^0-9][^0-9]*"," ")
              a = l.split()
              pCount1 = Integer.parseInt(a[0])
              pCount2 = Integer.parseInt(a[1])
          }
          

          String.findAll 解决方案更好! 等效:

          if (line.contains("RESULT:")) {
              a = line.findAll( /\d+/ )*.toInteger()
              pCount1 = a[0]
              pCount2 = a[1]
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2019-05-21
            • 1970-01-01
            • 1970-01-01
            • 2015-05-31
            • 2021-11-27
            相关资源
            最近更新 更多