代码之家  ›  专栏  ›  技术社区  ›  Nicolas Raoul

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

  •  1
  • Nicolas Raoul  · 技术社区  · 7 年前

    我已经编写了一个很小的Groovy脚本(只是一些简单的指令)并将其命名为 a-b.groovy .
    我的同事在运行它时遇到了问题,他说:

    我相信在Groovy脚本文件名中“-”是非法的

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

    (注:与 Naming convention for groovy script files ,我的问题不是关于惯例)

    2 回复  |  直到 7 年前
        1
  •  6
  •   Szymon Stepniak    7 年前

    最准确的答案是使用与命名Java类相同的标准来命名Groovy脚本。Groovy与Java类似,它支持Unicode字符编码,您可以 很可能 使用 任何Unicode字符

    每个Groovy脚本都被编译成一个Java类,该类扩展了 groovy.lang.Script 班级。它的名称取自Groovy脚本文件名。看看这个例子:

    所以meSimpleGroovyScript.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 a-b.groovy
    

    你甚至可以用 groovyc

    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类时使用下划线:

    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 -classpath ".:./groovy-all-2.4.12.jar" this_is_script
    

    使用 class.groovy 作为脚本名

    类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
    
        2
  •  3
  •   Michael Rutherfurd    7 年前

    由于脚本的文件名用于生成相应的类名,因此它将被限制为有效的java类名 Valid characters in a Java class name

    确切的定义在 Java Language Specification under section 3.8: Identifiers .

    数字,第一个必须是Java字母。。。

    字母和数字可以从整个Unicode字符集中提取, 是用他们的母语写的。

    序列)作为关键字(§3.9)、布尔文字(§3.10.3)或null 文字(§3.10.7),或出现编译时错误。

        3
  •  1
  •   ToYonos    5 年前

    我在文件名中包含破折号的脚本和具有 Closure 作为参数

    test-script.groovy :

    #!/usr/bin/env groovy
    
    void foo(String msg, Closure clo)
    {
        println msg
        clo()
    }
    
    foo 'bar', { -> println 'closure-bar'}
    

    在我的dev env上 Groovy 2.4.16

    bar
    closure-bar
    

    在prod env上 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)
    

    试验-脚本.groovy testScript.groovy ,它同时适用于版本2.4.16和2.4.5

    我找到了“错误修复程序”来 Groovy 2.4.15 . 在此版本之前,它失败了。

    这个 changelog