【问题标题】:A regex for a class definition in javajava中类定义的正则表达式
【发布时间】:2009-08-11 03:40:14
【问题描述】:

问题如下:

Java 中有一个庞大的代码库(数十个包中的数百个文件),我们需要能够在每个类定义中添加和删除关键字 strictfp。我打算使用 sed 或 awk 来执行此替换。但是,我想避免替换 cmets 或其他地方的“类”一词。谁能想到解决办法?

【问题讨论】:

  • 这是您想要执行的一次性任务,还是您想要在构建过程中完成的任务?另外,如果是后者,那么我很好奇为什么,只是出于兴趣?
  • 我们需要来回切换的能力,因为这是一个面向普通消费的科学包,如果人们怀疑,我们希望人们可以选择运行“严格”版本的程序舍入误差等。

标签: java regex sed awk gawk


【解决方案1】:

对于这样的任务,我首先建议编写一个小程序来验证目录树中的所有*.class 文件实际上是否具有(或不具有)正确的strictfp 设置。然后,无论您选择做什么来解决源代码修改问题,您都可以在编译器之后运行检查器,以确保您做对了。

这实际上只是应用于您的特定问题的 TDD。

【讨论】:

  • +1 考虑到缺少 strictfp 可能会导致结果不一致,这是一个非常好的主意
  • 这是个好主意。我假设您的意思是使用反射 API 来检查类?还是你在想别的?
  • 我实际上想到了类似 BCEL 的东西:jakarta.apache.org/bcel 您可以直接加载和检查 .class 文件,而无需打扰反射(而且我认为反射 API 甚至不会暴露strictfp 设置)。
【解决方案2】:

由于您想在 strictfp 和 no strictfp 之间来回切换,因此最好在构建过程中修改 .class 文件。然后,您可以将此选择作为构建选项并切换它,而无需不断更改源文件。

【讨论】:

  • 想进一步解释一下吗?我不知道有一种修改类文件的简单方法。不幸的是(而且令人抓狂)没有办法将 strictfp 指定为所有类的编译时或运行时选项。
  • 我没有尝试过,但是一些用于操作类文件的库,例如BCEL,应该可以做到。
【解决方案3】:

您的代码格式有多标准?例如,您能否在以{ 结尾的行或下一行以{ 或类似开头的行中查找“class”?

【讨论】:

  • 我是这么想的,但代码已经由几个不同的人编写了 3 年多。虽然格式通常是一致的,但有些代码部分的格式完全不同。 (大括号在同一行而不是下一行等)
  • 我想通过代码格式化程序运行它是一种选择,但这取决于您对格式化程序不会破坏代码的实际功能的信任程度;我没有太多经验与他们结合广泛的项目,所以我不能个人对这个选项发表意见。
【解决方案4】:

如果没有 java 解析器,就无法确定 100% 正确。但是,以下内容可能已经足够接近:

sed -i.bak 's/\\(public\\|private\\|protected\\)\\(.*\\)class/\\1 strictfp \\2 class/g' $file

我认为我的转义是正确的,但我是从 Windows 机器上写的,还没有测试过。

如果您的 cmets 带有 'public/private/protected' 后跟 'class',则上述内容会出错。

【讨论】:

  • 什么,你没有 Cygwin?说真的,明白了:-)
  • 我能看到的唯一问题是不需要 public/private/protected 关键字;如果没有这三个中的一个,则该类默认为包私有。
  • 这将跳过具有包访问级别(即无访问关键字)的类,并匹配“publicclass”之类的内容。
  • 哦,它也可以匹配public void foo() { ... A.class ... }
  • 它也会错过抽象类等,但这是一个很好的起点。谢谢
【解决方案5】:

作为一个完整的包罗万象,不,没有正则表达式。您基本上需要编写一个 Java 解释器(或至少是一个解析器)来解释类的任何理论构造。话虽如此,如果单词 class 是该行的第一个非空白位,或者如果它前面有一个访问修饰符是该行的第一个非空白位,那么您确实应该是安全的。

【讨论】:

    【解决方案6】:

    我能想到两种可能:

    • 使用解析器而不是正则表达式(RE 并不意味着一切)。解析器会更好地理解语言语法。
    • 使您的代码库保持一致,这样您就不会选择错误的“类”字符串。

    这些都不是很令人满意。第一个实际上很难写,第二个很难写。

    我的建议是找到一个 RE 并将其放在源代码的本地副本上,然后检查所有更改。无论做出错误的更改,调整 RE 并重试。

    然后引入编码标准,逐步将所有不符合的定义改正。

    【讨论】:

      【解决方案7】:

      星蓝:谢谢!通过查找 BCEL,我发现了 JMangler,它非常完美,因为我可以修改现有的 .class 文件以添加 strictfp 修饰符。 http://javalab.cs.uni-bonn.de/research/jmangler/tutorial/using.html

      【讨论】:

        【解决方案8】:

        只是为了让人们知道,我最终决定使用 Javassist 而不是 BCEL,因为 Javassist 似乎更易于使用并且完全适合我的目的。 http://csg.is.titech.ac.jp/~chiba/javassist 。 如果有人好奇,代码会是这样的:

        
            import javassist.*;
            ClassPool cp = new ClassPool(); 
            CtClass someClass = cp.get("SomeClass"); 
            someClass.setModifiers(Modifier.STRICT);
        

        【讨论】:

          猜你喜欢
          • 2013-01-18
          • 1970-01-01
          • 2015-12-29
          • 1970-01-01
          • 2015-04-27
          • 1970-01-01
          • 1970-01-01
          • 2018-05-03
          • 2013-11-18
          相关资源
          最近更新 更多