将命名空间添加到C++文件的脚本

问题描述:

所以我有巨大的代码库需要添加一个名称空间。我想用grep,xargs & sed将命名空间添加到所有的源文件中...将命名空间添加到C++文件的脚本

但我的技能没有达到标准。 理想

namespace foo 
{ 

将被添加后,所有的包括,并且在.h文件的#ENDIF后“}”补充。

对于.cpp文件,在所有包含之后添加'using namespace foo'就足够了。

我一直在搞sed,但还没有走得很远。

任何帮助,将不胜感激。谢谢!

+1

我推荐你使用脚本语言如Ruby,正则表达式用,来完成这项工作。根据您的需求和一些Ruby示例的Google搜索,您可以在30分钟到1小时内完成此脚本。你可以使用http://rubular.com/来测试你的正则表达式。 FWIW,我只写了一个Ruby脚本来查找所有.hpp和.cpp文件之间的名称空间/模块依赖关系 - 使用正则表达式花费了大约一个小时的时间。 – kfmfe04

+0

sed是将正则表达式用作处理文本的主要工具的早期程序之一。祝你们好运。 – shellter

这不是一件容易的事。的事情,使问题包括

  • 东西,你不希望你的新的命名空间内放置诸如
    • 结构,如中不属于自己的类language "C" { C-stuff }
    • 正向声明。如果你使用一些也不使用命名空间的外部软件包,这会比以前困难得多。
  • 即使找到在哪里放置namespace Foo {和结束'}'可能会很艰难。
    • 你确实想包含前向声明,除了那些不属于你的声明。
    • 您通常希望在文件范围内包含任何涉及一对大括号的内容,例如language C之类的内容。
    • 维护程序员(如果你的代码已经足够长)会为你的代码做各种不好的事情。他们会在类或函数内部,类和函数之间,任何地方提出声明,但顶部使脚本变得容易。
    • 你不想双重嵌套的东西。这很容易做到。
    • 由于各种原因,有些人在标题的末尾放置了看似无关的东西。这可能是一个特别讨厌的问题。
    • 如果您决定试图封装每个类,struct和枚举,您将必须找出声明的起始位置。你想包装template声明,如果有的话,当然还有doxygen注释等等。
    • 寻找课程的结束可能只是令人讨厌。人们有这种令人讨厌的倾向,把不匹配的大括号放在注释和字符串中。

祝你好运!一个脚本需要花费半个多小时才能写出来。这将比重写所有代码花费更少的时间。我建议你使用比sed更强大的东西。 Perl,python和ruby是三个不错的选择。

+0

我结束了手动转换... – anio

这让我半路上:

#!/bin/sh 
NAMESPACE=my_namespace 
for x in $(find . -name "*.h"); do 
    sed -i "$(grep -n "^#" $x | tail -2 | head -1 | sed 's/:.*//')a\\\nnamespace $NAMESPACE {\n" $x 
    sed -i "$(($(grep -n "^#" $x | tail -1 | sed 's/:.*//')-1))a} // namespace $NAMESPACE\n" $x 
done 

for x in $(find . -name "*.cpp"); do 
    sed -i "$(grep -n "#include" $x | tail -1 | sed 's/:.*//')a\\\nnamespace $NAMESPACE {\n" $x 
    echo >> $x 
    echo "} // namespace $NAMESPACE" >> $x 
done 

它主要定位在H文件中的一个,但最后预处理指令,并增加了命名空间存在。它会在最后一个预处理器指令之前产生命名空间(我假设我的h文件末尾有一个#endif)。如果情况并非如此,则可以相应地调整脚本。

在cpp的情况下,我寻找最后的包含来打开命名空间并关闭它在文件的末尾。

这并不完美,但面对100多个文件,它使工作更容易。

注意,这并没有考虑到结束后卫#endif的线路,但是将它们包裹在namespace {};似乎没有任何伤害。

根据您的喜好取消注释行。

#!/usr/bin/env bash 
namespace="namespace m {" 
pad=" " 

function processFile { 
    # dos2unix "$1" 
    local fn=$1 
    local tmp="$1.tmp" 
    echo "Processing '$fn'" 
    rm -f "$tmp" 
    local -i skipping=1 
    local regSkip="^(#include.*|#pragma.*|//.*|)"'$' 
    local line 
    while IFS= read -r line 
    do 
     if ((skipping)); then 
      if [[ $line =~ $regSkip ]]; then : 
      else skipping=0; echo "$namespace" >> "$tmp" 
      fi 
      echo "$line" >> "$tmp" 
     else 
      echo "$pad$line" >> "$tmp" 
     fi 
    done < "$1" 
    echo "$line" >> "$tmp" 
    echo "};" >> "$tmp" 
    mv -f "$fn" "$fn.ori" 
    # optionally reformat 
    astyle --options='e:\git\sfink.ini' < "$tmp" > "$fn" && rm "$tmp" 
    # else just move 
    # mv -f "$tmp" "$fn" 
} 

# for fn in $(find . -name '*.h'); do processFile "$fn"; done 
# for fn in $(find . -name '*.cpp'); do processFile "$fn"; done 
for fn in "[email protected]"; do processFile "$fn"; done 

注:另,文件必须使用UNIX换行符格式