Best way to work on multi-line output from external process called from groovy script?

I use this method:

def runProcess(List cmd) {
  def process = cmd.execute()
  def output = new StringWriter(), error = new StringWriter()
  process.waitForProcessOutput(output, error)
  def exitCode = process.exitValue()
  if (exitCode) {
    throw new Exception("Error: $error with code: $exitCode")
  }
  return output.toString().split()
}

To run external processes that can return one or multiple lines of output.

Sometimes I need to inspect each line and return a match if found. First I tried with an eachLine closure but found that I cannot return from that (Can you break from a Groovy "each" closure?):

def sample() {
  String tagName = ""
  def tags = runProcess(["git", "tag"])
  tags.eachLine { tag -> 
    println "tag $tag"
    if(tag = "mytag") {
      tagName = tag
      // Cannot return from a eachLine closure :-(
      return tag
    }
  }
  return tagName
}

The above will work but if I have 1000 lines it will go through all of them - since the return statement is ignored.

I am now trying with a classic for loop:

def sample() {

  def tags = runProcess(["git", "tag"])
  println "tags.getClass() "  + tags.getClass() // this is java.lang.String
  String[] tagsArr = tags.split("\n");
  println "tags.getClass() "  + tagsArr.getClass() // this is [Ljava.lang.String
     
  if (tagsArr != null && tagsArr.length > 0) { // does NOT = true when tagsArr is empty :-(
     for (String tag : tagsArr) {
        def desc = shellCommand(["git", "describe","--tags","$tag"])
        if(desc.trim() == "mytag") {
          println "Found tag: $tag at HEAD"
          return tag
        }
     }
  }
}

This is pretty verbose/ugly and does not work when tagsArr is empty (still investigating this and any input is appreciated!).

Any suggestions on how to implement better handling of multi-lines output from calling an external process?

Also this from above:

return output.toString().split()

does not seem right...

I have also looked at:

http://konstructcomputers.blogspot.com/2013/12/groovy-line-by-line-process-output.html

which looks quite verbose/extensive. I hoped that groovy offered some minimal way of doing this to avoid this kind of "low level" boilerplate code.

Sidenote. Interestingly enough this page:

http://docs.groovy-lang.org/latest/html/documentation/working-with-io.html

does not mention waitForProcessOutput which I thought was the most robust way to get output from an external process.



Read more here: https://stackoverflow.com/questions/68481010/best-way-to-work-on-multi-line-output-from-external-process-called-from-groovy-s

Content Attribution

This content was originally published by u123 at Recent Questions - Stack Overflow, and is syndicated here via their RSS feed. You can read the original post over there.

%d bloggers like this: