Groovy在对没有前导零的十进制值计算关系运算符时,会抱怨出现意外标记

Groovy在对没有前导零的十进制值计算关系运算符时,会抱怨出现意外标记,groovy,Groovy,我在执行下面的Groovy脚本片段时遇到了一个问题 GroovyShell sh = new GroovyShell(); sh.evaluate("\"abcd\".length() >= .34"); 我得到以下例外情况。整个堆栈跟踪如下所述 Exception in thread "main" org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed: Script1.groovy:

我在执行下面的Groovy脚本片段时遇到了一个问题

GroovyShell sh = new GroovyShell();
sh.evaluate("\"abcd\".length() >= .34");
我得到以下例外情况。整个堆栈跟踪如下所述

Exception in thread "main" org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
Script1.groovy: 1: unexpected token: >= @ line 1, column 17.
    "abcd".length() >= .34d
如果我将
.34
更改为
0.34
,它会工作。但是,由于某些限制,我将无法更改脚本内容。 如有任何帮助,我们将不胜感激

我得到以下例外情况

Exception in thread "main" org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
Script1.groovy: 1: unexpected token: >= @ line 1, column 17.
    "abcd".length() >= .34d
                       ^
1 error

at org.codehaus.groovy.control.ErrorCollector.failIfErrors(ErrorCollector.java:310)
at org.codehaus.groovy.control.ErrorCollector.addFatalError(ErrorCollector.java:150)
at org.codehaus.groovy.control.ErrorCollector.addError(ErrorCollector.java:120)
at org.codehaus.groovy.control.ErrorCollector.addError(ErrorCollector.java:132)
at org.codehaus.groovy.control.SourceUnit.addError(SourceUnit.java:350)
at org.codehaus.groovy.antlr.AntlrParserPlugin.transformCSTIntoAST(AntlrParserPlugin.java:144)
at org.codehaus.groovy.antlr.AntlrParserPlugin.parseCST(AntlrParserPlugin.java:110)
at org.codehaus.groovy.control.SourceUnit.parse(SourceUnit.java:234)
at org.codehaus.groovy.control.CompilationUnit$1.call(CompilationUnit.java:168)
at org.codehaus.groovy.control.CompilationUnit.applyToSourceUnits(CompilationUnit.java:943)
at org.codehaus.groovy.control.CompilationUnit.doPhaseOperation(CompilationUnit.java:605)
at org.codehaus.groovy.control.CompilationUnit.processPhaseOperations(CompilationUnit.java:581)
at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:558)
at groovy.lang.GroovyClassLoader.doParseClass(GroovyClassLoader.java:298)
at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:268)
at groovy.lang.GroovyShell.parseClass(GroovyShell.java:688)
at groovy.lang.GroovyShell.parse(GroovyShell.java:700)
at groovy.lang.GroovyShell.evaluate(GroovyShell.java:584)
at groovy.lang.GroovyShell.evaluate(GroovyShell.java:623)
at groovy.lang.GroovyShell.evaluate(GroovyShell.java:594)
at groovytest.Testtest.main(Testtest.java:18)

Groovy代码段不正确-如果十进制数小于
1.0
,Groovy不支持不带前导零的表示法。如果您试图直接使用
groovyc
编译以下表达式:

"abcd".length() >= .34
编译将失败,错误如下:

org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
test.groovy: 2: Unexpected input: '.' @ line 2, column 20.
   "abcd".length() >= .34
                      ^

1 error
Java支持这种表示法,但是Groovy从
2.x
3.0.0-alpha-3
版本都不支持这种表示法

固溶体 修复输入Groovy代码段,使其仅包含有效且可编译的代码。任何无效的Groovy语句或表达式都将导致失败和编译错误

解决方法:使用
replaceAll()
方法添加前导零 编译此类错误代码段的唯一方法是将所有
\d+
(点后跟至少一个空格并以数字结尾)替换为
0.$1
。考虑下面的例子:

def snippet=“\”abcd\”.length()>=0.34;\“efgh\”.length()>=0.22;\“xyz\”.length()>=0.11
println snippet.replaceAll('\\.(\\d+),'0.$1')
它将
0
添加到缺少前导零的所有十进制数中。运行此示例会将以下输出打印到控制台:

"abcd".length() >= 0.34; "efgh".length() >= 0.22; "xyz".length() >= 0.11;
如果您将修改后的代码段传递给
GroovyShell.evaluate()
方法,它将无错误地运行

当然,这不是一个坚如磐石的解决方案,它只是一种自动修复代码段中引入的一些语法错误的方法。有些情况下,这种变通方法可能会导致一些副作用,您必须意识到这一点


谢谢你,西蒙。你提到的我已经知道了。由于对内容的编辑有限制,我无法以编程方式进行编辑。还想知道Groovy的限制是什么,它要求小数<1的前导0。0@user353949但是您是否执行
sh.evaluate(snippet)
?如果调用
sh.evaluate(snippet)
,则可以修改输入。如果没有,那么在创建Groovy代码段时,您必须请求修复它。我看不到任何其他修复方法-问题的根源在于Groovy编译器接收到无法编译的代码,除了以这种或那种方式修复代码之外,没有其他方法。您还可以使用自己的类扩展
GroovyShell
,并重写
evaluate(字符串代码)
方法将所有`.\d+`替换为`0.$1`,然后使用此自定义GroovyShell实现。但这实际上与答案中建议的解决方案相同——如果可以提供自定义GroovyShell,那么在调用
evaluate()
方法时,很可能可以修改常规GroovyShell的输入;这里的正则表达式替换问题很棘手,根据您的示例,它将失败,因为它将.123替换为0.123。有没有办法通过处理这类拐角案例来解决问题?@user353949它不会将
“.123 asdf”
替换为
“0.123 asdf”
,因为
replaceAll
中使用的模式要求
之前至少有一个空格。当然,在
“.123 asdf”
的情况下,它将以
“0.123 asdf”
结束。这不是一个防弹的解决方案,但您真正的问题是您必须处理甚至不编译的Groovy代码段。