【问题标题】:Java Code formatting using shell script使用 shell 脚本格式化 Java 代码
【发布时间】:2010-11-11 09:32:12
【问题描述】:

我知道这很愚蠢,但我无法克服我的好奇心。是否可以编写一个shell脚本来格式化一段java代码?

例如,如果用户编写代码:

    public class Super{
    public static void main(String[] args){
    System.out.println("Hello world");
    int a=0;
    if(a==100)
    {
    System.out.println("Hello world");
    }
    else
    {
    System.out.println("Hello world with else");
    }
    }
}

我想写一个 shell 脚本,让代码变成这样。

 public class Super
 {
  public static void main(String[] args)
  {
   System.out.println("Hello world");
   int a=0;
   if(a==100){
    System.out.println("Hello world");
   }
   else{
    System.out.println("Hello world with else");
   }
}

准确地说,我们应该改变花括号的格式。如果是 try/catch 或控制结构,我们应该将其更改为同一行,如果是函数/方法/类,则应在下一行。我对 sed 和 awk 知之甚少,它们可以轻松完成此任务。我也知道这可以使用 eclipse 来完成。

【问题讨论】:

标签: java unix shell scripting


【解决方案1】:

好吧,我手头有一些空闲时间,所以我决定重温我过去的 linux 美好时光:]

在阅读了一些关于 awk 和 sed 的内容后,我决定最好同时使用这两种方法,因为在 awk 中添加缩进并在 sed 中解析字符串更容易。

这是格式化源文件的 ~/sed_script:

 # 删除缩进
    s/^ \+//g

    # 用类格式化行
    s/^\(.\+class.\+\) *\({.*\)$/\1\n\2/g

    # 用方法格式化行
    s/^\(public\|private\)\(\+static\)\?\(\+void\)\? \+\(.\+(.*)\) *\({.*\)$/\1\2\3 \4\n\5/g

    # 用其他结构格式化行
    /^\(if\|else\|for\|while\|case\|do\|try\)\([^{]*\)$/,+1 { # 得到不包含'{'的行
                                                            # 连同下一行
      /.*{.*/ d # 用'{'删除下一行
      s/\([^{]*\)/\1 {/g # 并在第一行添加'{'
    }

这里是添加缩进的 ~/awk_script:

 开始 { 深度 = 0 }
    /}/ { 深度 = 深度 - 1 }
          {
              获取前缀(深度)
              打印前缀 $0
          }
    /{/ { 深度 = 深度 + 1 }

          函数getPrefix(深度){
              前缀 = ""
              for (i = 0; i 

然后你就这样使用它们:

 > sed -f ~/sed_script ~/file_to_format > ~/.tmp_sed
    > awk -f ~/awk_script ~/.tmp_sed

它远非正确的格式化工具,但我希望它可以作为示例脚本供参考:] 祝你学习顺利。

【讨论】:

  • Kirill,我复制了你的sed_script,但由于某种原因,我在"/^\(if\|else\..." 线上收到了一个命令乱码错误。知道可能是什么原因吗?
【解决方案2】:

一种快速但有缺陷的尝试,但适用于您的示例输入:

BEGIN {depth = 0;}
/{$/  {depth = depth + 1}
/^}/  {depth = depth - 1}
      {prefix = ""; for (i = 0; i < depth; i++) { prefix = prefix "  "} print prefix $0 ; }

这是一个 awk 脚本:将它放在一个文件中并执行

awk -f awk_script_file source_file

这方面的明显缺陷包括:

  • 它不会捕捉到你想要缩进的无括号的地方

    if (foo)
      bar();
    
  • 它将根据 cmets 中的大括号和字符串文字修改缩进深度

  • 它不会检测 { 大括号后跟 cmets

【讨论】:

    【解决方案3】:

    我认为这可以通过一个简单的“sed”脚本来完成。 使用 1 个变量 (bCount) 存储“{”(左括号)的数量 -(减去)“}”(右括号)的数量 然后我会浏览文件并根据使用的括号的实际数量插入“标签”。 所以

    public class Super{ //bCount=0
    public static void main(String[] args){ //bCount=1
    System.out.println("Hello world"); //bCount=2
    int a=0; //bCount=2
    ....and so on
    

    所以在第 0 行插入 0 个标签

    第 1 行有 1 个标签

    第 3 行和第 4 行有 2 个选项卡,依此类推...

    【讨论】:

    • 你能详细说明一下...我语法很差
    【解决方案4】:

    绝对有可能...我只是不明白您为什么要花时间做这件事? :] 有足够的工具可以做到这一点,任何体面的 IDE 都提供了一种重新格式化源代码(包括 Eclipse)的方法。

    例如,要在 Eclipse 3.4 中格式化(在其他版本中应该类似),只需右键单击您的项目或文件,然后从菜单中选择“Source > Format”。

    如果您需要更改格式化代码的方式,只需转到“Preferences > Java > Code Style > Formatter”并更改模板。据我所知,它在 JDeveloper 和 NetBeans 中非常相似。

    【讨论】:

    • 是的,伙计。只是想了解更多关于 sed 和 awk 的信息。我认为一些专家会对此有所了解。即使我曾提到它很愚蠢 :)
    • 哦,对不起 :) 也许你应该从阅读他们的手册页和一些关于使用正则表达式的信息开始?
    【解决方案5】:

    看看CLI for Jalopy。 Jalopy 是一个非常强大的源格式化程序。

    【讨论】:

    • 我只是想知道是否可以通过 shell 脚本来完成。有很多软件可以格式化代码,但我想问是否可以使用 awk 或 sed
    • 很公平。虽然我会在您问题的顶部明确说明您这样做是作为 sed/awk 的学习练习,否则您会得到很多像我一样的答案
    • 同意。 Shell 脚本执行程序。如果程序数量有限,您应该在问题中提及。我想这个问题是因为有人想重新格式化大量文件,或者想在提交到源存储库时重新格式化。我建议脚本调用 vim,这是非常灵活的重新格式化功能。
    【解决方案6】:

    考虑使用Jindent,这是一个“使用 Emacs 的简单 Java 缩进工具”。这是一个免费的 shell 脚本,是伯克利托勒密项目的一部分。

    【讨论】:

      猜你喜欢
      • 2016-02-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-12
      • 2018-09-08
      • 1970-01-01
      • 2011-02-22
      • 2011-05-24
      相关资源
      最近更新 更多