【问题标题】:Using bash command line, how to add "import package.name.*;" to many java files?使用 bash 命令行,如何添加“import package.name.*;”很多java文件?
【发布时间】:2010-11-04 17:41:39
【问题描述】:

我正在考虑使用 find 或 grep 来收集文件,也许可以使用 sed 来进行更改,但是如何处理输出?还是在vim中使用“argdo”会更好?

注意:这个问题要求的是命令行解决方案,而不是 IDE。建议 IDE 的答案和 cmets 将被冷静、礼貌和平静地标记出来。 :-)

【问题讨论】:

    标签: bash vim command-line refactoring sed


    【解决方案1】:

    我实际上已经开始在 vim 中使用“argdo”了。首先,设置参数:

    :args **/*.java
    

    “**”遍历所有子目录,“args”将它们设置为 arg 列表(就好像您启动 vim 时将所有这些文件作为 vim 的参数一样,例如:vim package1/One.java package1 /Two.java package2/One.java)

    然后摆弄我需要的任何命令来进行我想要的转换,例如:

    :/^package.*$/s/$/\rimport package.name.*;/
    

    “/^package.*$/”作为其后普通“s///”替换的地址; "/$/" 匹配包行的结尾; "\r" 是换行符。

    现在我可以使用 argdo 对所有文件自动执行此操作。我点击“:”,然后向上箭头得到上面的行,然后插入“argdo”,这样它就变成了:

    :argdo /^package.*$/s/$/\rimport package.name.*;/
    

    此“argdo”将该转换应用于参数列表中的每个文件。

    这个解决方案的真正好处在于它并不危险:它实际上还没有更改文件,但我可以查看它们以确认它是否符合我的要求。我可以撤消特定文件,或者如果我不喜欢它所做的事情,我可以退出(顺便说一句:我已将 ^n 和 ^p 映射到 :n 和 :N 以便我可以快速浏览文件)。现在,我用 ":wa" - "write all" 文件提交它们。

    :wa
    

    此时,我仍然可以撤消特定文件,或根据需要对它们进行微调。

    同样的方法可用于其他重构(例如,在许多文件中更改方法签名并调用它)。


    顺便说一句:这很笨拙:“s/$/\rtext/”...必须有更好的方法从 vim 的命令行附加文本...

    【讨论】:

    • 对于一般重构,如果你要打开一个 IDE,你应该诚实地使用 eclipse。我是一个巨大的 VIM 偏执狂(见我的头像),但支持 vararg 启用语言的 GUI 将真正成为你的失败,因为我了解到做与上述几乎相同的事情。
    • 好吧,除了你的头像,我不会从其他人那里得到它...... :-) 我不明白你的第二句话:你所说的启用“vararg”的语言是什么意思撤消? (我使用的是 Java,但我不经常使用变量参数)
    【解决方案2】:

    您也可以使用 ed 命令进行文件内搜索和替换:

    # delete all lines matching foobar 
    ed -s test.txt <<< $'g/foobar/d\nw' 
    

    见:http://bash-hackers.org/wiki/doku.php?id=howto:edit-ed

    【讨论】:

      【解决方案3】:
      for i in `ls *java`
      do 
        sed -i '.old' '1 i\
        Your include statement here.
        ' $i
      done
      

      应该这样做。 -i 进行就地替换, .old 保存旧文件以防万一出现问题。根据需要替换迭代器 *java(可能是 'find . | grep java' 或其他东西。)

      【讨论】:

      • 谢谢,那一定是手册页的 [SUFFIX] 部分 - 看到示例后更有意义。
      【解决方案4】:

      我是以下的忠实粉丝

      export MYLIST=`find . -type f -name *.java`
      for a in $MYLIST; do
         mv $a $a.orig
         echo "import.stuff" >> $a
         cat $a.orig >> $a
         chmod 755 $a 
      done;
      

      mv 是邪恶的,最终会得到你。但我在很多事情上都使用了同样的结构,它是我选择的实用刀。

      更新:此方法还备份您应该使用任何方法执行的文件。此外,它只使用 shell 的功能。您不必记忆您不经常使用的工具。教一只猴子(相信我我已经做到了)很简单。而且您通常足够明智地将它扔掉,因为它花了四秒钟的时间来写。

      【讨论】:

      • 我想避免使用临时文件,但你是对的:如果它有效,为什么不呢?
      • 它唯一的优点是它不需要任何外壳功能之外的东西。它可以在 bash 和 ksh 中运行,而且比在 perl 和其他愚蠢的小东西上提神醒脑要快。
      • 更新中的优点,尤其是备份作为副作用。
      • 简单而且有效。我在循环末尾添加了一个 rm $a.orig 以删除 tmp 文件
      【解决方案5】:

      您可以使用sed 在文件的第一行之前插入一行:

      sed -ie "1i import package.name.*;" YourClass.java
      

      使用 for 循环遍历所有文件并在它们上运行此表达式。但是如果你有包要小心,因为import 语句必须在包声明之后。如果是这种情况,您可以使用更复杂的 sed 表达式。

      【讨论】:

      • 谢谢,这就是我在看到混乱的答案后想出的,除了“1i”和“import”之间的非重要空格。我不知道这是允许的 - 它更清楚。 sed 可以在匹配行之后追加,例如 sed -ie "/^package/a import package.name.*;" eg.java # 但它也会匹配以 package 开头的任何其他行,而不仅仅是第一行...
      【解决方案6】:

      如果有一种体面的方法可以“仅对第一行执行此操作”,我会使用 sed,但我不知道有哪一种方法是我想不到的。为什么不改用 perl。比如:

      find . -name '*.java' -exec perl -p -i.bak -e '
          BEGIN {
            print "import package.name.*;\n"
          }' {} \;
      

      应该做的工作。更多详情请查看perlrun(1)

      【讨论】:

      • 谢谢,我同意 Perl 是这种文本处理的明智选择,尽管我刚刚得到 sed 来完成插入部分:sed -ie '1i\\nimport package.name.*; ' eg.java#“1”是第一行; “我”是插入
      • 不错。我不记得您是否可以在 sed 中使用裸行号作为地址。另一种选择是 awk,但如果不是基本替换,我倾向于 perl。
      【解决方案7】:

      我建议sed -i 避免担心输出的需要。由于您没有指定您的平台,请检查您的手册页; sed -i 的语义因 Linux 和 BSD 而异。

      【讨论】:

      • 谢谢,我不知道。 (我尝试将输出重定向到原始文件,但这使其长度为零)。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-12-06
      • 2017-06-13
      • 2014-12-26
      • 2020-08-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多