Groovy脚本文件名中的禁止字符?

时间:2018-07-09 05:45:11

标签: groovy filenames hyphen

我写了一个很小的Groovy脚本(仅需几个简单的说明),并将其命名为a-b.groovy
我的同事在运行它时遇到麻烦,说:

  

我相信Groovy脚本文件名中的'-'是非法的

问题:什么是Groovy文件名中非法字符的完整列表?

(注意:与Naming convention for groovy script files不同,我的问题与约定无关)

3 个答案:

答案 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();
}


Groovy脚本名称的正确情况

即使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未指示任何相关的修复程序,因此它可能已包含在另一个错误修复程序中。

无论如何,我在这个案子上呆了几个小时,所以如果它可以帮助某人,那就好!