Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/28.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 通过Shell向所有函数的开头和结尾添加日志语句 我有一个项目,它有1000个以上的C++源文件存储在同一目录下的不同文件夹中。我想在这些.cpp文件中定义的所有函数的开头和结尾添加日志代码。请参见下面的示例: //SomeSrcFile.cpp //Sample ReturnType SomeClass::SomeFunc1(InputParameters) { ...... } ReturnType SomeClass::SomeFunc2(InputParameters) { ...... } 输出_Python_Linux_Bash_Shell_Awk - Fatal编程技术网

Python 通过Shell向所有函数的开头和结尾添加日志语句 我有一个项目,它有1000个以上的C++源文件存储在同一目录下的不同文件夹中。我想在这些.cpp文件中定义的所有函数的开头和结尾添加日志代码。请参见下面的示例: //SomeSrcFile.cpp //Sample ReturnType SomeClass::SomeFunc1(InputParameters) { ...... } ReturnType SomeClass::SomeFunc2(InputParameters) { ...... } 输出

Python 通过Shell向所有函数的开头和结尾添加日志语句 我有一个项目,它有1000个以上的C++源文件存储在同一目录下的不同文件夹中。我想在这些.cpp文件中定义的所有函数的开头和结尾添加日志代码。请参见下面的示例: //SomeSrcFile.cpp //Sample ReturnType SomeClass::SomeFunc1(InputParameters) { ...... } ReturnType SomeClass::SomeFunc2(InputParameters) { ...... } 输出,python,linux,bash,shell,awk,Python,Linux,Bash,Shell,Awk,如何为这种工作编写shell脚本?这里可以用awk吗 更新 我认为通过AWK可以像那样做。但我还没有想出用我的方式去做 我只想使用Bash或Python来实现这一点,因为它们是我现在唯一熟悉的工具 更新2 也许这项工作真的很辛苦,超出了我的预料。但是如果我不在乎准确性呢?如果我不关心函数包含在注释等中的情况,该怎么办?有没有一种简单的方法可以做到这一点?请参阅您粘贴的帖子,下面是代码: awk 'BEGIN{X=FS} { if ($0~/void/ && $0 ~/\(

如何为这种工作编写shell脚本?这里可以用awk吗

更新

  • 我认为通过AWK可以像那样做。但我还没有想出用我的方式去做

  • 我只想使用Bash或Python来实现这一点,因为它们是我现在唯一熟悉的工具

  • 更新2

    也许这项工作真的很辛苦,超出了我的预料。但是如果我不在乎准确性呢?如果我不关心函数包含在注释等中的情况,该怎么办?有没有一种简单的方法可以做到这一点?

    请参阅您粘贴的帖子,下面是代码:

    awk 'BEGIN{X=FS}
        { if ($0~/void/ && $0 ~/\(/) split($0,a,FS);split(a[2],b,"(")
          FS="";OFS="";
             for (i=1; i<=NF; i++)
                 if ($i == "{") {
                     if (++d == "1") $i=sprintf("{\n\tchar FuncName[] = \"%s()\";\n\tprintf(\"%%s begins\\n\", FuncName);\n",b[1]);
                 } else {if ($i == "}") {
                     if (d-- == "1") $i=sprintf("\n\tprintf(\"%%s end\\n\", FuncName);\n\t} ",b[1]);
                   }
                 } 
           FS=X;OFS=X
         }1' infile.cpp
    


    如果您不介意它不是健壮的,那么对于简单一致的情况,使用GNU awk作为第三个参数to match()和字符类的缩写(例如
    \w
    ):

    对于其他AWK,只需在regexp中使用
    [[:space:][]
    而不是
    \s
    [:alnum:][uuu]
    而不是
    \w
    ,并使用
    match()
    substr()
    和/或
    sub()
    的组合从匹配regexp的字符串中提取函数名,例如:

    $ cat tst2.awk
    BEGIN {
        beg = "\tchar FuncName[] = \"%s()\";\n\tprintf(\"%%s begins\\n\", FuncName);\n"
        end = "\n\tprintf(\"%%s ends\\n\", FuncName);"
    }
    /^[[:space:]]*[[:alnum:]_]+[[:space:]]+([[:alnum:]_]+::[[:alnum:]_]+)[(][^)]*[)]/ {
        funcName = $0
        gsub(/^[[:space:]]*[[:alnum:]_]+[[:space:]]+|[(][^)]*[)].*/,"",funcName)
    }
    /{/ && (++braceCnt == 1) { $0 = $0 ORS sprintf(beg,funcName) }
    /}/ && (--braceCnt == 0) { $0 = sprintf(end,funcName) ORS $0 }
    { print }
    

    我建议在C++中使用一种不同的方法。 <>这只会简化shell脚本的需要,但会得到更好的C++代码。 简而言之,我建议创建一个跟踪类和一组宏来部署它。这有很多好处:

    • 易于添加、删除、更改、打印输出
    • 自动处理文件名、函数名、行号等
    • 无论函数存在于何处都有效(这比您的方法有很大改进)
    创建一个跟踪类,该类接受诸如函数名、文件名、行#等参数-任何您想要打印出来的参数。每当构造跟踪类时,它都会打印函数条目消息。每当跟踪类超出范围并被销毁时,它都会打印一条函数退出消息

    下面是类声明:

    // File: Trace.h
    
    class Trace                                                                                                                  
    {
    public:
       // print function entry message
       Trace(const char *name,                                                                                                   
             const char *file,                                                                                                   
             const int line, 
             int traceOn = -1, // used for enabling/disabling Trace printing 
                               // within a particular call chain.
             const void* thisPtr = 0);                                                                                           
    
       // print function exit message
       ~Trace();                                                                                                                 
    
       static bool active;                                                                                                       
    
    private:
       std::string* theFunctionName;                                                                                             
       std::string* theFileName;
       int          theLineNumber;                                                                                               
       const void*  theThisPtr;                                                                                                  
       static int   layer; // used for printout indenting
       static std::list<clock_t> startTimeList; // used for printing timing information                                                                                 
       bool         previouslyActive;                                                                                            
    };
    
    现在,要使用跟踪类,您需要执行以下操作:

    //SomeSrcFile.cpp      
    //Sample  
    
    #define TRACE_ENABLED // comment this out to disable tracing in this file.
    #include "Trace.h"
    
    ReturnType SomeClass::SomeFunc1(InputParameters)        
    {
         TRACE__
         ......
    }
    
    ReturnType SomeClass::SomeFunc2(InputParameters) {
         TRACE__
         ......
    }
    
    现在,跟踪类的一个潜在实现是: //文件:Trace.C

    #include "Trace.h"
    
    bool Trace::active = true;
    int  Trace::layer = 0;
    std::list<clock_t> Trace::startTimeList;
    
    Trace::Trace(const char *name, 
                 const char *file, 
                 const int line, 
                 int traceOn,  // default: -1
                 const void* thisPtr) // default:  0 
    : theFunctionName(0),
      theFileName(0),
      theLineNumber(0),
      theThisPtr(thisPtr),
      previouslyActive(active)
    {
       if (active)
       {
          theFunctionName = new std::string(name);
          theFileName     = new std::string(file);
          theLineNumber   = line;
    
          std::cout<<"---> Trace: ";
          for( int L = 0; L < layer; ++L )
          {
             std::cout<<"   ";
          }
          std::cout
             <<"{ Entered "
             << *theFileName << ":" 
             << theLineNumber << " " 
             << *theFunctionName << "()";
    
          if(thisPtr > 0)
          {
             std::cout<<"  this = "<< thisPtr;
          }
          std::cout<< std::endl;
    
          layer++;
          startTimeList.push_back(clock());
       }
    
       if(traceOn >= 0)
       {
          active = traceOn;
          if (active && !previouslyActive)
          {
             std::cout<<"+++] Trace: Enabled"<<std::endl;
          }
          else if (previouslyActive && !active)
          {
             std::cout<<"+++[ Trace: Disabled"<<std::endl;
          }
       }
    }
    
    Trace::~Trace()
    {
       if (previouslyActive && !active)
       {
          std::cout<<"+++] Trace: Enabled"<<std::endl;
       }
       else if (active && !previouslyActive)
       {
          std::cout<<"+++[ Trace: Disabled"<<std::endl;
       }
    
       active = previouslyActive;
    
       if (active || theFunctionName)
       {
          layer--;
          double startTime = static_cast<double>(startTimeList.back());
          startTimeList.pop_back();
          double endTime = static_cast<double>(clock());
          double elapsedTime = (endTime-startTime)/CLOCKS_PER_SEC;
    
          std::cout<<"<--- Trace: ";
          for( int L = 0; L < layer; ++L )
          {
             std::cout<<"   ";
          }
    
          std::cout<<"} Leaving "
                   << *theFileName << ":" 
                   << theLineNumber <<" "
                   << *theFunctionName <<"()";
          if(theThisPtr > 0)
          {
             std::cout<<"  this = "<< theThisPtr;
          }
    
          std::cout<<"  elapsedTime = "<<elapsedTime<<"s";
          std::cout<< std::endl;
    
          delete theFunctionName;
          delete theFileName;
       }
    }
    
    #包括“Trace.h”
    bool Trace::active=true;
    int Trace::layer=0;
    std::list Trace::startTimeList;
    跟踪::跟踪(常量字符*名称,
    常量字符*文件,
    常量整数行,
    int-traceOn,//默认值:-1
    const void*thisPtr)//默认值:0
    :函数名(0),
    文件名(0),
    线号(0),
    本PTR(本PTR),
    先前活动(活动)
    {
    如果(活动)
    {
    函数名=新的std::string(名称);
    theFileName=newstd::string(文件);
    线号=线;
    
    std::coutMay我想问一下您想要完成什么?可能有比日志语句更有用的东西。这样的程序通常也需要解析语法(这不是直接编写的)…例如,下面的字符串定义
    char greeting[]=“void SomeFunc1”;
    可能会让一个简单的解析器误以为它是一个真正函数的开始。注释也可能包含字符串,这会让解析器感到困惑,所以它也需要解析注释…@HåkonHægland是对的,没有C解析器,您无法可靠地完成这项工作。shell脚本如何知道它看到
    void SomeFunc2(…){ <代码> >它是否在C样式注释分隔符内,例如,调试像这样的打印语句是个坏主意。但是如果您要这样做,请考虑诸如“代码>打印”(“%s开始\n”)、“{函数”)。
    使用预处理器通过
    \uuuuu func\uuuuu
    获取函数名,然后定义宏打印,可以取消定义以删除打印语句。除了修改代码,还有什么呢?虽然我没有使用它们,但似乎有可视化工具可供使用,以使其密集格式更易于理解。sh首先,在快速搜索中,谢谢。EdMorton。我删除了领先的代码>代码> >。我想你是说这个规则适用于C预处理器,对吗?你的答案不解决在子目录中修改1000个C++源文件的问题。@ MytInu:YUP,如我的“答案”中所述:“这只会稍微简化您的shell脚本需要。“因此,不,它实际上没有回答问题。我认为它重新引导问题,以寻求更好的最终结果。通常情况下,我认为这类事情应该是注释而不是答案,但我肯定不能将所有代码都放入注释中。你的答案主要只是一条注释,大意是“如果你的1000个C++代码文件是这样写的,你就不会有问题了。”他们说,事后聪明通常是20/20个……马蒂诺:实际上,我的回答是一个评论:“你将尝试用一个类似AWK的脚本做一些事情,我认为你应该用它做些别的事情。”“我的意思是,提出问题的人应该添加一个宏,而不是一对打印语句。这与现有代码无关。它所做的是使awk任务变得更简单(每个函数体只添加一个单词)还有一个更有用的最终结果。这将处理注释行,如猫躲避狗(和狼)
    就好像它是一个函数定义,而为函数返回类型识别关键字的方法永远不适用于一般代码,因为函数可以返回用户定义的类型。此外,您不需要说
    $0~/void/
    ,只要
    /void/
    $ awk -f tst.awk file
        //SomeSrcFile.cpp
        //Sample
        ReturnType SomeClass::SomeFunc1(InputParameters)
        {
            char FuncName[] = "SomeClass::SomeFunc1()";
            printf("%s begins\n", FuncName);
    
             ......
    
            printf("%s ends\n", FuncName);
        }
    
        ReturnType SomeClass::SomeFunc2(InputParameters) {
            char FuncName[] = "SomeClass::SomeFunc2()";
            printf("%s begins\n", FuncName);
    
             ......
    
            printf("%s ends\n", FuncName);
        }
    
    $ cat tst2.awk
    BEGIN {
        beg = "\tchar FuncName[] = \"%s()\";\n\tprintf(\"%%s begins\\n\", FuncName);\n"
        end = "\n\tprintf(\"%%s ends\\n\", FuncName);"
    }
    /^[[:space:]]*[[:alnum:]_]+[[:space:]]+([[:alnum:]_]+::[[:alnum:]_]+)[(][^)]*[)]/ {
        funcName = $0
        gsub(/^[[:space:]]*[[:alnum:]_]+[[:space:]]+|[(][^)]*[)].*/,"",funcName)
    }
    /{/ && (++braceCnt == 1) { $0 = $0 ORS sprintf(beg,funcName) }
    /}/ && (--braceCnt == 0) { $0 = sprintf(end,funcName) ORS $0 }
    { print }
    
    // File: Trace.h
    
    class Trace                                                                                                                  
    {
    public:
       // print function entry message
       Trace(const char *name,                                                                                                   
             const char *file,                                                                                                   
             const int line, 
             int traceOn = -1, // used for enabling/disabling Trace printing 
                               // within a particular call chain.
             const void* thisPtr = 0);                                                                                           
    
       // print function exit message
       ~Trace();                                                                                                                 
    
       static bool active;                                                                                                       
    
    private:
       std::string* theFunctionName;                                                                                             
       std::string* theFileName;
       int          theLineNumber;                                                                                               
       const void*  theThisPtr;                                                                                                  
       static int   layer; // used for printout indenting
       static std::list<clock_t> startTimeList; // used for printing timing information                                                                                 
       bool         previouslyActive;                                                                                            
    };
    
    #ifdef TRACE_ENABLED // define the real macros
    #undef TRACE_ENABLED // must be re #defined preceding each '#include "Trace.h" '    
    #define TRACE__     Trace tr_( __FUNCTION__ , __FILE__ , __LINE__, -1, this );                                             
    #define TRACE_OFF__ Trace tr_off_(__FUNCTION__ , __FILE__ , __LINE__, false);                                              
    #define TRACE_ON__  Trace tr_on_(  __FUNCTION__ , __FILE__ , __LINE__, true);                                              
    
    #else // DUMMY MACROS: if TRACE_ENABLED is not defined.                                                                      
    
    #define TRACE__
    #define TRACE_ON__
    #define TRACE_OFF__                                                                                                        
    
    #endif        
    
    //SomeSrcFile.cpp      
    //Sample  
    
    #define TRACE_ENABLED // comment this out to disable tracing in this file.
    #include "Trace.h"
    
    ReturnType SomeClass::SomeFunc1(InputParameters)        
    {
         TRACE__
         ......
    }
    
    ReturnType SomeClass::SomeFunc2(InputParameters) {
         TRACE__
         ......
    }
    
    #include "Trace.h"
    
    bool Trace::active = true;
    int  Trace::layer = 0;
    std::list<clock_t> Trace::startTimeList;
    
    Trace::Trace(const char *name, 
                 const char *file, 
                 const int line, 
                 int traceOn,  // default: -1
                 const void* thisPtr) // default:  0 
    : theFunctionName(0),
      theFileName(0),
      theLineNumber(0),
      theThisPtr(thisPtr),
      previouslyActive(active)
    {
       if (active)
       {
          theFunctionName = new std::string(name);
          theFileName     = new std::string(file);
          theLineNumber   = line;
    
          std::cout<<"---> Trace: ";
          for( int L = 0; L < layer; ++L )
          {
             std::cout<<"   ";
          }
          std::cout
             <<"{ Entered "
             << *theFileName << ":" 
             << theLineNumber << " " 
             << *theFunctionName << "()";
    
          if(thisPtr > 0)
          {
             std::cout<<"  this = "<< thisPtr;
          }
          std::cout<< std::endl;
    
          layer++;
          startTimeList.push_back(clock());
       }
    
       if(traceOn >= 0)
       {
          active = traceOn;
          if (active && !previouslyActive)
          {
             std::cout<<"+++] Trace: Enabled"<<std::endl;
          }
          else if (previouslyActive && !active)
          {
             std::cout<<"+++[ Trace: Disabled"<<std::endl;
          }
       }
    }
    
    Trace::~Trace()
    {
       if (previouslyActive && !active)
       {
          std::cout<<"+++] Trace: Enabled"<<std::endl;
       }
       else if (active && !previouslyActive)
       {
          std::cout<<"+++[ Trace: Disabled"<<std::endl;
       }
    
       active = previouslyActive;
    
       if (active || theFunctionName)
       {
          layer--;
          double startTime = static_cast<double>(startTimeList.back());
          startTimeList.pop_back();
          double endTime = static_cast<double>(clock());
          double elapsedTime = (endTime-startTime)/CLOCKS_PER_SEC;
    
          std::cout<<"<--- Trace: ";
          for( int L = 0; L < layer; ++L )
          {
             std::cout<<"   ";
          }
    
          std::cout<<"} Leaving "
                   << *theFileName << ":" 
                   << theLineNumber <<" "
                   << *theFunctionName <<"()";
          if(theThisPtr > 0)
          {
             std::cout<<"  this = "<< theThisPtr;
          }
    
          std::cout<<"  elapsedTime = "<<elapsedTime<<"s";
          std::cout<< std::endl;
    
          delete theFunctionName;
          delete theFileName;
       }
    }