如何在Groovy脚本中读取Bash heredoc的标准输入

时间:2016-03-17 12:41:18

标签: bash groovy

我试图让Groovy脚本读取标准输入,所以我可以用带有heredoc的Bash脚本调用它,但是我得到java.lang.NullPointerException: Cannot invoke method readLine() on null object例外。

这是一个简洁的Groovy脚本echo.groovy

#!/usr/bin/env groovy
for (;;)
{
    String line = System.console().readLine()
    if (line == null)
        break
    println(">>> $line")
}

这里是等效的Ruby脚本echo.rb

#!/usr/bin/env ruby
ARGF.each do |line|
  puts ">>> #{line}"
end

如果我从Bash shell调用它们,一切都按预期工作:

$ ./echo.rb 
one
>>> one
two
>>> two
three
>>> three
^C
$ ./echo.groovy 
one
>>> one
two
>>> two
three
>>> three
^C

这是使用heredocs的Bash脚本heredoc.sh

echo 'Calling echo.rb'
./echo.rb <<EOF
one
two
three
EOF
echo 'Calling echo.groovy'
./echo.groovy <<EOF
one
two
three
EOF

当我运行它时会发生这种情况:

$ ./heredoc.sh 
Calling echo.rb
>>> one
>>> two
>>> three
Calling echo.groovy
Caught: java.lang.NullPointerException: Cannot invoke method readLine() on null object
java.lang.NullPointerException: Cannot invoke method readLine() on null object
        at echo.run(echo.groovy:4)

有什么想法吗?

更新

在Etan的建议中,我将echo.groovy更改为以下内容:

#!/usr/bin/env groovy
Reader reader = new BufferedReader(new InputStreamReader(System.in))
for (;;)
{
    String line = reader.readLine()
    if (line == null)
        break
    println(">>> $line")
}

它现在适用于heredocs:

$ ./heredoc.sh 
Calling echo.rb
>>> one
>>> two
>>> three
Calling echo.groovy
>>> one
>>> two
>>> three

谢谢Etan。如果您想发布正式答案,我会提出建议。

2 个答案:

答案 0 :(得分:1)

正如Etan所说,你需要阅读System.in我认为这会得到你的回应

#!/usr/bin/env groovy
System.in.withReader { r ->
    r.eachLine { line ->
        println ">>> $line"
    }
}

认为它与Ruby版本不完全相同,因为ARGF将返回参数(如果有的话)

答案 1 :(得分:1)

作为Etan答案的替代方案,Groovier方法是withReader方法,后者处理读取器的清理,以及BufferedReader的eachLine方法,它处理无限循环。

#!/usr/bin/env groovy

System.in.withReader { console ->
    console.eachLine { line ->
        println ">>> $line"
    }
}