zoukankan      html  css  js  c++  java
  • 【转】如何编写Python脚本替换文件中的多行字符

     在大概3个月之前,Python对我来说一直是个迷。然而,就在3个月前我经理给我一个任务——删除(替换)所有项目源码文件中包含特定几行内容的所有注释。整个项目源码的大小有1G,在Linux服务器(中高档)上编译需要半个多小时,可见代码量之大,不可能手动去一个一个改。肯定得用脚本去处理,于是我想到了Python。在这之前没有接触过Python,花了2个星期一顿恶补之后,总算顺利交差了。

    一直很想和大家分享一下碰到的问题及我如何解决的(可能我的方案并不好,但是他能够解决我的问题),但一直拖到现在是因为我感觉我还对Python的了解还不够。因为要在短时间内完成上面交下来的任务,在学习Python的时候,都是走马观花,对解决自己的问题不相关的直接跳过,看资料也静不下心,脑海里都是问题。前几天我静下心把Python的书从头到尾浏览了一遍,感觉现在是时候要进行总结了。

    本文的主要内容如下:

    问题描述 
    解题思路 
    代码实现 
    Python的特点 
    1、问题描述
    项目源码很大,属于C/C++混合的那种,编程风格也很多样,有'.c'、'.cc'、'cpp'、'.h'、'.hh'等文件。我要完成的任务是:把包含特定几行内容的注释删掉,如(声明:下面的内容只是我随便举的一个例子,项目源码中不涉及下面的内容。)

    /* 
    * Copyright 2002 Sun Microsystems, Inc. All rights reserved.

    *

    * Redistribution and use in source and binary forms, with or without

    * modification, are permitted provided that the following conditions

    * are met:

    *

    * - Redistributions of source code must retain the above copyright

    * notice, this list of conditions and the following disclaimer.

    *

    * - Redistribution in binary form must reproduce the above copyright

    * notice, this list of conditions and the following disclaimer in

    * the documentation and/or other materials provided with the

    * distribution.

    *

    * Neither the name of Sun Microsystems, Inc. or the names of

    * contributors may be used to endorse or promote products derived

    * from this software without specific prior written permission.

    */

    但是格式有很多种,如有的在“ Copyright 2002 Sun Microsystems, Inc. All rights reserved.”前面有一段关于本源码文件的描述、有的在“from this software without specific prior written permission.”后面有一段关于本源码文件的描述、有的是C++风格的注释用"//",而不是“/**/”、还有的没有

    “ * - Redistribution in binary form must reproduce the above copyright

    * notice, this list of conditions and the following disclaimer in

    * the documentation and/or other materials provided with the

    * distribution.”等等还有其他一些。总之一句话,我要删除的包含特定几行内容的注释有很多中格式!

    于是我决定要用Python来编写脚本处理。要匹配特定的内容,我想到了用正则表达式,但苦于不知道如何去构建正则来匹配上面描述的内容(您知道的话,希望能够告诉我)!我只有另辟路径了。

    2、解题思路
    我的思路——要删除所有项目源码中包含特定几行内容的注释,脚本要满足以下几点功能:

    脚本要能够遍历所有的源码文件('.c'、'.cc'、'cpp'、'.h'、'.hh'),并只处理上面的几种类型的文件 
    找出包含特定几行内容的注释,并删除之 
    能够处理一些特殊情况,如软连接文件 
    上面的几点的处理步骤可以表示如下:

    Step 1:输入要处理源码文件夹名,或者源码文件名;

    Step 2:如果是文件名,检查文件的类型是否为'.c'、'.cc'、'cpp'、'.h'、'.hh',否则不处理;

    Step 3:检查文件是否是软连接,如果是软连接则不处理;

    Step 4:查找文件中是否存在匹配的注释,存在则删掉,否则不处理;

    Step 5:如果是文件夹,则对文件夹中的每个文件、文件夹进行处理,转Step2.

    思路很明确,关键是如何查找文件中是否包含匹配的内容,并删除!还有就是,对于一个没用过Python等脚本语言的人来说,如何编码实现也是一个问题!

    如何确定注释是否为包含特定几行内容的注释?我的思路如下:(因为正则表达式学的不好,只有通过下面的方法了)

    如果是/*、//则记录下当前的文件行数,即行号startLine 
    以行为单位查找是否存在特定的几行,如“ Copyright 2002 Sun Microsystems, Inc. All rights reserved.”等等 
    直到遇到*/,或注释结束了(对于//)。如果存在,则记录下注释结束的行号endLine 
    最后,删掉这从startLine ~ endLine的内容。 
    3、代码实现
    废话我不多说了,直接按照上面的实例实现代码,如果你对Python不熟,请参阅相关资料。
    #!/usr/bin/env python
    #
    Filename: comment.py

    import os, sys, fileinput

    #-------------------------------------------------------------
    def usage():
        
    print u'''
        help: comment.py <filename | dirname>

        [dirname]: Option, select a directory to operate
        [filename]: Option, select a file to operate

        Example: python comment.py /home/saylor/test
        
    '''
    #--------------------------------------------------------------
    def commentFile(src, fileList):
        
    '''
        description: comment files
        param src: Operate file name
        
    '''
        
    #if file exist?
        ifnot os.path.exists(src):
            
    print'Error: file - %s doesn\'t exist.'% src
            return False
        
    if os.path.islink(src):
            
    print'Error: file - %s is just a link, will not handle it.'
            
    return False
        filetype 
    = (os.path.splitext(src))[1]
        
    ifnot filetype in ['.c','.h']:
            
    return False
        
    try:
            
    ifnot os.access(src, os.W_OK):
                os.chmod(src, 
    0664)
        
    except:
            
    print'Error: you can not chang %s\'s mode.'% src
        try:
            inputf 
    = open(src, 'r')
            outputfilename 
    = src +'.tmp'
            outputf 
    = open(outputfilename, 'w')
        beginLine 
    = 0
        endLine 
    =100000000
        isMatched 
    = False

        
    #-----find the beginLine and endLine -------------------
            for eachline in fileinput.input(src):
            
    if eachline.find('/*'>= 0:
            beginLine 
    = fileinput.lineno()
            
    if eachline.find('Copyright 2002 Sun Microsystems, Inc. All rights reserved.'>= 0:
                isMatched 
    = True
            
    if eachline.find('*/'>= 0 and isMatched:
            endLine 
    = fileinput.lineno()
            
    break
        
        
    #-----delete the content between beginLine and endLine-----
        print beginLine, endLine
        lineNo 
    =1
        
    for eachline in inputf:
            
    if lineNo < beginLine:
            
    print eachline
            outputf.write(eachline)
            
    elif lineNo > endLine:
            
    print eachline
            outputf.write(eachline)
            lineNo 
    = lineNo +1
            
            inputf.close()
            outputf.close()
            os.rename(outputfilename, src)
            fileList.append(src)
        
    except:
            
    print'Error: unexcept error.'
            inputf.close()
            outputf.close()
        
    return True

    #--------------------------------------------------------------
    def commentDir(src, fileList):
        
    '''
        description:
             comment files in src(dir)
        param src:
             operate files in src(dir)
        
    '''
        
    #if dir exist?
        ifnot os.path.exists(src):
            
    print'Error: dir - %s is not exist.'%s (src)
            
    return False
        filelists 
    = os.listdir(src)
        
    for eachfile in filelists:
            eachfile 
    = src +'/'+eachfile
            
    if os.path.isdir(eachfile):
                commentDir(eachfile, fileList)
            
    elif os.path.isfile(eachfile):
                commentFile(eachfile, fileList)
        
    return True

    #--------------------------------------------------------------
    def main():
        
    if len(sys.argv) <2:
            usage()
            sys.exit(
    1)
        src 
    = sys.argv[1]
        
    if os.path.isdir(src):
            dire 
    = os.path.abspath(src)
            dirFlag 
    = True
        
    elif os.path.isfile(src):
            fl 
    = os.path.abspath(src)
            dirFlag 
    = False
        
    else:
            
    print'Error'
        fileList 
    = []
        
    if dirFlag:
            commentDir(dire, fileList)
        
    else:
            commentFile(fl, fileList)
        
    if fileList:
            
    print'Successful handle file: ...'
            
    for eachfile in fileList:
                
    print eachfile
        
    print'Done'
        
    return True

    #--------------------------------------------------------------
    if__name__=='__main__':
        main()

  • 相关阅读:
    创建型-单例模式(Singleton)
    创建型-抽象工厂模式(Abstract Factory)
    创建型-工厂模式(Factory Method)
    excel数据查找/匹配/合并--vlookup公式使用
    【分库分表/读写分离】学习+整理
    java中main方法的参数的作用
    JVM指令码手册
    bug:Caused by: java.lang.OutOfMemoryError: GC overhead limit exceeded
    sql:基础总结
    转:【host文件作用】
  • 原文地址:https://www.cnblogs.com/swordzj/p/2731761.html
Copyright © 2011-2022 走看看