Parsing 如何在Groovy中解析文本

Parsing 如何在Groovy中解析文本,parsing,text,groovy,functional-programming,Parsing,Text,Groovy,Functional Programming,我需要解析文本(svn命令的输出)以检索数字(svn修订版)。 这是我的密码。注意,我需要以文本形式检索所有输出流以执行其他操作 def proc = cmdLine.execute() // Call *execute* on the strin proc.waitFor() // Wait for the command to finish def output = proc.in.text //这

我需要解析文本(svn命令的输出)以检索数字(svn修订版)。 这是我的密码。注意,我需要以文本形式检索所有输出流以执行其他操作

def proc = cmdLine.execute()                 // Call *execute* on the strin
proc.waitFor()                               // Wait for the command to finish
def output = proc.in.text
//这里发生的其他事情

output.eachLine {
    line ->
    def revisionPrefix = "Last Changed Rev: "
    if (line.startsWith(revisionPrefix)) res = new Integer(line.substring(revisionPrefix.length()).trim())
}
这段代码运行得很好,但由于我还是Groovy的新手,我想知道是否有更好的惯用方法来避免丑陋的if

svn输出示例(当然问题更一般)

我从下面的答案中得到了灵感,并使用find()解决了这个问题。我的解决办法是:

def revisionPrefix = "Last Changed Rev: "
def line = output.readLines().find { line -> line.startsWith(revisionPrefix) }
def res = new Integer(line?.substring(revisionPrefix.length())?.trim()?:"0")

3行,无if,非常干净

一个可能的替代方案是:

def output = cmdLine.execute().text
Integer res = output.readLines().findResult { line ->
  (line =~ /^Last Changed Rev: (\d+)$/).with { m ->
    if( m.matches() ) {
      m[ 0 ][ 1 ] as Integer
    }
  }
}
不确定是不是更好。我相信其他人会有不同的选择

编辑: 另外,请注意使用
proc.text
。如果你的进程输出了很多东西,那么当inputstream满的时候你可能会阻塞

下面是一个有大量注释的备选方案,使用
consumeProcessOutput

// Run the command
String output = cmdLine.execute().with { proc ->

  // Then, with a StringWriter
  new StringWriter().with { sw ->

    // Consume the output of the process
    proc.consumeProcessOutput( sw, System.err )

    // Make sure we worked
    assert proc.waitFor() == 0

    // Return the output (goes into `output` var)
    sw.toString()
  }
}

// Extract the version from by looking through all the lines
Integer version = output.readLines().findResult { line ->

  // Pass the line through a regular expression
  (line =~ /Last Changed Rev: (\d+)/).with { m ->

    // And if it matches
    if( m.matches() ) {

      // Return the \d+ part as an Integer
      m[ 0 ][ 1 ] as Integer
    }
  }
}

您考虑过使用Java SVN库吗?是的,但我还需要从命令行启动其他命令。不管怎么说,问题是关于提高我的groovy技能,总的来说,我对这个解决方案非常满意。我标记为解决方案,因为使用readLines让我想到将它与findAll结合起来删除if
// Run the command
String output = cmdLine.execute().with { proc ->

  // Then, with a StringWriter
  new StringWriter().with { sw ->

    // Consume the output of the process
    proc.consumeProcessOutput( sw, System.err )

    // Make sure we worked
    assert proc.waitFor() == 0

    // Return the output (goes into `output` var)
    sw.toString()
  }
}

// Extract the version from by looking through all the lines
Integer version = output.readLines().findResult { line ->

  // Pass the line through a regular expression
  (line =~ /Last Changed Rev: (\d+)/).with { m ->

    // And if it matches
    if( m.matches() ) {

      // Return the \d+ part as an Integer
      m[ 0 ][ 1 ] as Integer
    }
  }
}