我写了一个很小的Groovy脚本(仅需几个简单的说明),并将其命名为a-b.groovy
。
我的同事在运行它时遇到麻烦,说:
我相信Groovy脚本文件名中的'-'是非法的
问题:什么是Groovy文件名中非法字符的完整列表?
(注意:与Naming convention for groovy script files不同,我的问题与约定无关)
答案 0 :(得分:3)
最准确的答案是使用与命名Java类相同的标准来命名Groovy脚本。与Java类似,Groovy支持Unicode字符编码,您可以很可能使用任何Unicode字符作为脚本名称(这并不意味着您应该这样做)。>
每个Groovy脚本都被编译为扩展groovy.lang.Script
类的Java类。它的名称取自Groovy脚本文件名。看一下这个例子:
someSimpleGroovyScript.groovy
println "test"
当我们使用groovyc someSimpleGroovyScript.groovy
进行编译时,我们将看到一个类文件someSimpleGroovyScript.class
。现在,让我们看一下该类的外观:
javap someSimpleGroovyScript
我们会得到这样的东西:
Compiled from "someSimpleGroovyScript.groovy"
public class someSimpleGroovyScript extends groovy.lang.Script {
public static transient boolean __$stMC;
public someSimpleGroovyScript();
public someSimpleGroovyScript(groovy.lang.Binding);
public static void main(java.lang.String...);
public java.lang.Object run();
protected groovy.lang.MetaClass $getStaticMetaClass();
}
即使Java类命名标准适用于Groovy脚本名称,Groovy也支持一些特殊情况。
-
字符您可以将脚本命名为a-b.groovy
并作为Groovy脚本运行:
groovy a-b.groovy
您甚至可以使用groovyc
对其进行编译,以获取以下Java类:
Compiled from "a-b.groovy"
public class a-b extends groovy.lang.Script {
public static transient boolean __$stMC;
public a-b();
public a-b(groovy.lang.Binding);
public static void main(java.lang.String...);
public java.lang.Object run();
protected groovy.lang.MetaClass $getStaticMetaClass();
}
即使该类名对于Java编译器来说是不正确的,您仍然可以使用Java运行它(您需要将groovy-all
添加到类路径中):
java -classpath ".:./groovy-all-2.4.12.jar" a-b
$
在Groovy中,您甚至可以将脚本称为123$.groovy
,并且可以简单地将其运行为:
groovy 123\$.groovy
但是,当将此脚本编译为Java类时,Groovy编译器将使用下划线替换$
:
javap 123_
输出:
Compiled from "123$.groovy"
public class 123_ extends groovy.lang.Script {
public static transient boolean __$stMC;
public 123_();
public 123_(groovy.lang.Binding);
public static void main(java.lang.String...);
public java.lang.Object run();
protected groovy.lang.MetaClass $getStaticMetaClass();
}
您仍然可以使用Java运行这样的编译脚本:
java -classpath ".:./groovy-all-2.4.12.jar" 123_
您还可以在脚本名称中使用空格,例如this is script.groovy
可以执行为:
groovy this\ is\ script.groovy
Groovy编译器将用下划线替换每个空格:
Compiled from "this is script.groovy"
public class this_is_script extends groovy.lang.Script {
public static transient boolean __$stMC;
public this_is_script();
public this_is_script(groovy.lang.Binding);
public static void main(java.lang.String...);
public java.lang.Object run();
protected groovy.lang.MetaClass $getStaticMetaClass();
}
您仍然可以使用Java运行这样的编译脚本:
java -classpath ".:./groovy-all-2.4.12.jar" this_is_script
class.groovy
作为脚本名称它甚至更进一步。您可以创建一个名为class.groovy
的脚本,该脚本将编译为以下Java类:
Compiled from "class.groovy"
public class class extends groovy.lang.Script {
public static transient boolean __$stMC;
public class();
public class(groovy.lang.Binding);
public static void main(java.lang.String...);
public java.lang.Object run();
protected groovy.lang.MetaClass $getStaticMetaClass();
}
javac
编译器永远不允许您使用此类名称编译类,但是java
在运行此类字节码方面没有问题:
java -classpath ".:./groovy-all-2.4.12.jar" class
答案 1 :(得分:2)
由于脚本的文件名用于生成相应的类名,因此它将限于有效的Java类名 Valid characters in a Java class name
您几乎可以使用任何字符,包括大多数Unicode字符! 确切的定义在Java Language Specification under section 3.8: Identifiers中。
标识符是Java字母和Java的无限长度序列 数字,其中第一个必须是Java字母。 ...
字母和数字可能来自整个Unicode字符集, ...这使程序员可以在程序中使用标识符 是用他们的母语写的。
标识符不能具有相同的拼写(Unicode字符 序列)作为关键字(§3.9),布尔文字(§3.10.3)或null 文字(§3.10.7),否则会发生编译时错误。
答案 2 :(得分:1)
我遇到了一个奇怪的问题,即脚本中的文件名中包含破折号,并且该函数的参数为Closure
让我们考虑这个例子test-script.groovy
:
#!/usr/bin/env groovy
void foo(String msg, Closure clo)
{
println msg
clo()
}
foo 'bar', { -> println 'closure-bar'}
在带有Groovy 2.4.16
的开发环境中,它像一个超级按钮一样工作,并显示:
bar
closure-bar
在带有Groovy 2.4.5
的产品环境中,出现此错误:
Caught: java.lang.ClassFormatError: Illegal class name "test-script$foo" in class file test-script$foo
java.lang.ClassFormatError: Illegal class name "test-script$foo" in class file test-script$foo
at test-script.run(test-script.groovy:9)
如果我将test-script.groovy
重命名为testScript.groovy
,则它适用于2.4.16和2.4.5版本。
我找到了“错误修复”到Groovy 2.4.15
。在此版本之前,它失败了。
此版本的changelog未指示任何相关的修复程序,因此它可能已包含在另一个错误修复程序中。
无论如何,我在这个案子上呆了几个小时,所以如果它可以帮助某人,那就好!