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

niknxzdl  于 2022-11-01  发布在  其他
关注(0)|答案(3)|浏览(133)

我编写了一个很小的Groovy脚本(只有几条简单的指令),并将其命名为a-b.groovy
我的同事在运行它时遇到了麻烦,他说:
我认为'-'在Groovy脚本文件名中是非法

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

5m1hhzi4

5m1hhzi41#

最准确的答案是使用与我们命名Java类相同的标准来命名Groovy脚本。Groovy与Java类似,支持Unicode字符编码,您可以 * 最有可能使用任何Unicode字符**作为脚本名称(这并不意味着您应该这样做)。
每个Groovy脚本都被编译成一个扩展groovy.lang.Script类的Java类。它的名称取自Groovy脚本文件名。看一下这个例子:

  • 一些简单的Groovy脚本。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

但是,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运行这样编译的脚本:

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
wixjitnu

wixjitnu2#

由于脚本的文件名用于生成相应的类名,因此将限制为有效的java类名Valid characters in a Java class name
您几乎可以使用任何字符,包括大多数Unicode字符!确切的定义在Java语言规范的3.8节中:标识符。
一个标识符是一个无限长的Java字母和Java数字序列,其中第一个必须是Java字母。
字母和数字可以从整个Unicode字符集中提取,...这允许程序员在他们的程序中使用以他们的母语编写的标识符。
标识符不能与关键字(参见3.9节)、布尔型文字(参见3.10.3节)或空文字(参见3.10.7节)有相同的拼写(Unicode字符序列),否则会发生编译时错误。

0mkxixxg

0mkxixxg3#

我遇到了一个奇怪的问题,脚本的文件名中包含一个破折号,函数的参数为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的prod env上,我收到以下错误:

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版本
我追踪到了X1 M6 N1 X的“bug修复”。在这个版本之前,它失败了。
此版本的changelog未指出任何相关修复,因此可能已包含在另一个错误修复中。
不管怎么说,我已经被这个案子困了几个小时了,所以如果它能帮助别人,那是好事!

相关问题