用于将命名空间添加到c ++文件的脚本

时间:2011-10-31 20:58:17

标签: c++ regex linux sed

所以我有一个巨大的代码库,需要添加一个命名空间。而不是手动执行此操作,我想到使用grep,xargs& sed将命名空间添加到所有源文件......

但是我的技能达不到标准。 理想情况下

namespace foo 
{

将在所有包含之后添加,并在.h文件中的#endif之后添加'}'。

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

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

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

3 个答案:

答案 0 :(得分:3)

这不是一件容易的事。导致问题的因素包括

  • 您不希望放入新命名空间的内容,例如
    • language "C" { C-stuff }
    • 这样的构造
    • 不属于您的类的前向声明。如果您使用的是一些也不使用名称空间的外部程序包,这会变得难n倍。
  • 即使找到放置namespace Foo {和关闭'}'的位置也很难。
    • 您确实要附上前瞻性声明,但不属于您的声明除外。
    • 您通常希望将任何内容包含在涉及一对大括号的文件范围内 - language C之类的内容除外。
    • 维护程序员(如果你的代码已经存在足够长的时间)将会对你的代码造成各种不好的事情。他们会在类或函数内部,类和函数之间提出声明,但顶部会使脚本很容易。
    • 你不想双重嵌套。这样做非常容易。
    • 由于各种原因,有些人在标题的末尾放置了看似无关紧要的内容。这可能是一个特别令人讨厌的问题。
    • 如果您决定尝试附上每个类,结构和枚举,您将不得不弄清楚声明的开始位置。你想要包装template声明,如果有的话,当然还有doxygen评论等。
    • 找到课程的结尾可能只是讨厌。人们有这种讨厌的倾向,在评论和字符串中添加不匹配的括号。
祝你好运!一个脚本需要花费半个多小时来编写。它将比重写所有代码花费更少的时间。我建议你使用比sed更强大的东西。 Perl,python和ruby是三个不错的选择。

答案 1 :(得分:1)

这让我走了一半:

#!/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的情况下,我查找最后一个include来打开命名空间并在文件末尾关闭它。

这远非完美,但面对100多个文件,它使工作变得更加轻松。

答案 2 :(得分:0)

注意,这并没有考虑关闭后卫#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 "$@"; do processFile "$fn"; done

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

System.Drawimg.Imaging

n.b。,文件必须采用unix换行格式