用于更改C ++类名的脚本

时间:2010-02-22 21:39:31

标签: c++ perl bash sed cygwin

我已将类从全局命名空间移动到特定命名空间。我也改变了班级名称。我想将使用这些类的所有源文件转换为新格式。我在思考使用Cygwin上的bash文件的sed脚本或执行perl脚本。我在使用bash脚本时遇到了麻烦。

这是我正在尝试执行的过程:

  1. 对于每个源文件,* .cpp和 * .hpp,递归:
  2. 如果文件包含旧类 名称,然后转换文件。
  3. 结束。
  4. Bash脚本中的问题是检测文件是否包含旧类名。我在为每个类名考虑一个grep语句:

    for f in `find . -iname \*.[ch]pp`;
    do
      if [ grep "Field_Blob_Medium" $f -eq 0 || grep "Field_Boolean" ]; then
          sed -f conversion.sed $f
      fi
    done
    

    问题是只有一个命令可以在Bash if语句中,使用以下语法:

    if grep "Field_Unsigned_Short" $f;
    

    因此我无法对grep s进行逻辑或。

    我可以执行嵌套循环,但我不知道如何break for Bash for循环:

    OLD_CLASS_NAMES="Field_Blob_Medium Field_Boolean Field_Unsigned_Int"
    for f in `find . -iname \*.[ch]pp`;
    do
      for c_name in $OLD_CLASS_NAMES;
      do
         if grep $c_name $f then
            sed -f convert.sed $f # <-- Need to break out of inner loop after this execution.
         fi
      done
    done
    

    所以我正在寻找有关如何处理包含旧类名的每个源文件并将其转换为新类的建议。尽管Perl脚本也可以接受,但首选Cygwin Bash脚本示例。 此外,在将转换后的内容写入new文件之前,脚本应制作原始源文件的备份副本。

    我在Windows XP和Windows Vista上运行Cygwin。

3 个答案:

答案 0 :(得分:2)

不要回避Perl:它使这项任务变得容易!

#! /usr/bin/perl -i.bak

use warnings;
use strict;

my $old = join "|" => qw(
  Field_Blob_Medium
  Field_Boolean
  Field_Unsigned_Int
);

chomp(@ARGV = `find . -iname \*.[ch]pp -print0 |
               xargs -0 grep -lE '($old)'`);

unless (@ARGV) {
  warn "$0: nothing to do!\n";
  exit 0;
}

while (<>) {
  s[Field_Blob_Medium]  [my::ns::MediumBlob]g ||
  s[Field_Boolean]      [my::ns::Bool]g       ||
  s[Field_Unsigned_Int] [my::ns::UInt]g;

  print;
}

-i开关用于就地编辑。它会自动创建备份并将转换后的结果写入原始位置。

设置@ARGV就好像你只用那些包含旧类名的*.cpp*.hpp文件调用了程序。 -E切换为grep可启用扩展正则表达式,因此未转义的()|是元字符。

如果没有命中(,如果@ARGV为空),则无事可做。

否则,对于每个具有旧名称的文件的每一行(Perl为您处理的机制!),尝试将Field_Blob_Medium重命名为my::ns::MediumBlob,依此类推。请注意,这些替换尝试在第一次成功后停止,因此如果一行包含两个不同的旧名称,则一个将被替换,另一个将保持不变。

通常替换运算符是s///,但您可以使用上面的包围分隔符。我这样做是为了给新名字辩护。

当然,这是您实际替换的替身。

最后,print可能修改的行,由于-i将其写入更新的源文件。

答案 1 :(得分:1)

这个工作在我的linux上。它管理其他人指出的各种事情:

#!/bin/bash
OLD_NAMES="(EField_Blob_Medium|Field_Boolean|Field_Unsigned_Int)"

find "$1" -name "*.hpp" -o -name "*.cpp" -print0 | \
   xargs -0 --replace grep -E "${OLD_NAMES}" {} && sed -i.save -f convert.sed {}

重要的是:

  • 使用-0 of xar的find -print0选项管理带空格的文件。它使用'null'ASCII char作为分隔符。 xargs的-0选项将'null'字符理解为分隔符:您正确管理带空格的文件名。
  • --replace选项用于将当前处理的文件替换为“{}”字符串
  • sed的-i选项使用.save
  • 备份文件
  • &amp;&amp;作为if的捷径。表达式的第二部分仅在第一部分为真时才有效

希望它有所帮助, MY2C

答案 2 :(得分:0)

您可以使用grep的regex选项为您的搜索提供更大的灵活性。根据你的例子:

if [ grep "Field_Blob_Medium" $f -eq 0 || grep "Field_Boolean" ];

可能是

if [ grep -E "(Field_Blob_Medium|Field_Boolean)" ... ];

你可以将这些'|'串在心里。

另外,你可以将你的发现合并到你的greps

find . -name "*.hpp" or -name "*.cpp" | xargs grep -E ...

...如果你想在那里简化那个循环。