萬盛學電腦網

 萬盛學電腦網 >> 網絡編程 >> 編程語言綜合 >> 如何編寫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)
      &

copyright © 萬盛學電腦網 all rights reserved