如何編寫Python腳本替換文件中的多行字符?
來(lái)源:易賢網(wǎng) 閱讀:1119 次 日期:2014-08-20 14:45:06
溫馨提示:易賢網(wǎng)小編為您整理了“如何編寫Python腳本替換文件中的多行字符?”,方便廣大網(wǎng)友查閱!

問題描述

解題思路

代碼實(shí)現(xiàn)

Python的特點(diǎn)

1、問題描述

項(xiàng)目源碼很大,屬于C/C++混合的那種,編程風(fēng)格也很多樣,有'.c'、'.cc'、'cpp'、'.h'、'.hh'等文件。我要完成的任務(wù)是:把包含特定幾行內(nèi)容的注釋刪掉,如(聲明:下面的內(nèi)容只是我隨便舉的一個(gè)例子,項(xiàng)目源碼中不涉及下面的內(nèi)容。)

/*

* 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.”前面有一段關(guān)于本源碼文件的描述、有的在“from this software without specific prior written permission.”后面有一段關(guān)于本源碼文件的描述、有的是C++風(fēng)格的注釋用"http://",而不是“/**/”、還有的沒有

“ * - 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.”等等還有其他一些??傊痪湓?,我要?jiǎng)h除的包含特定幾行內(nèi)容的注釋有很多中格式!

于是我決定要用Python來(lái)編寫腳本處理。要匹配特定的內(nèi)容,我想到了用正則表達(dá)式,但苦于不知道如何去構(gòu)建正則來(lái)匹配上面描述的內(nèi)容(您知道的話,希望能夠告訴我)!我只有另辟路徑了。

2、解題思路

我的思路——要?jiǎng)h除所有項(xiàng)目源碼中包含特定幾行內(nèi)容的注釋,腳本要滿足以下幾點(diǎn)功能:

腳本要能夠遍歷所有的源碼文件('.c'、'.cc'、'cpp'、'.h'、'.hh'),并只處理上面的幾種類型的文件

找出包含特定幾行內(nèi)容的注釋,并刪除之

能夠處理一些特殊情況,如軟連接文件

上面的幾點(diǎn)的處理步驟可以表示如下:

Step 1:輸入要處理源碼文件夾名,或者源碼文件名;

Step 2:如果是文件名,檢查文件的類型是為'.c'、'.cc'、'cpp'、'.h'、'.hh',否則不處理;

Step 3:檢查文件是否是軟連接,如果是軟連接則不處理;

Step 4:查找文件中是否存在匹配的注釋,存在則刪掉,否則不處理;

Step 5:如果是文件夾,則對(duì)文件夾中的每個(gè)文件、文件夾進(jìn)行處理,轉(zhuǎn)Step2.

思路很明確,關(guān)鍵是如何查找文件中是否包含匹配的內(nèi)容,并刪除!還有就是,對(duì)于一個(gè)沒用過(guò)Python等腳本語(yǔ)言的人來(lái)說(shuō),如何編碼實(shí)現(xiàn)也是一個(gè)問題!

如何確定注釋是否為包含特定幾行內(nèi)容的注釋?我的思路如下:(因?yàn)檎齽t表達(dá)式學(xué)的不好,只有通過(guò)下面的方法了)

如果是/*、//則記錄下當(dāng)前的文件行數(shù),即行號(hào)startLine

以行為單位查找是否存在特定的幾行,如“ Copyright 2002 Sun Microsystems, Inc. All rights reserved.”等等

直到遇到*/,或注釋結(jié)束了(對(duì)于//)。如果存在,則記錄下注釋結(jié)束的行號(hào)endLine

最后,刪掉這從startLine ~ endLine的內(nèi)容。

3、代碼實(shí)現(xiàn)

廢話我不多說(shuō)了,直接按照上面的實(shí)例實(shí)現(xiàn)代碼,如果你對(duì)Python不熟,請(qǐng)參閱相關(guān)資料。

#!/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()

4、Python的特點(diǎn)

Python入門我強(qiáng)烈推薦下面的資料,深入學(xué)習(xí)請(qǐng)閱讀其它資料:

《A Byte of Python》http://www.swaroopch.com/notes/Python

《簡(jiǎn)明 Python 教程》http://woodpecker.org.cn/abyteofpython_cn/chinese/

Python的設(shè)計(jì)哲學(xué)是“優(yōu)雅”、“明確”、“簡(jiǎn)單”。因此,Perl語(yǔ)言中“總有多種方法來(lái)做同一件事”的理念在Python開發(fā)者中通常是難以忍受的。Python開發(fā)者的哲學(xué)是“用一種方法,最好是只有一種方法來(lái)做一件事”。在設(shè)計(jì)Python語(yǔ)言時(shí),如果面臨多種選擇,Python開發(fā)者總會(huì)拒絕花哨的語(yǔ)法,而選擇明確的沒有或者很少有歧義的語(yǔ)法。由于這種設(shè)計(jì)觀念的差異,Python源代碼通常認(rèn)為比Perl具備更好的可讀性。

Python開發(fā)人員盡量避開不成熟或者不重要的優(yōu)化。一些針對(duì)非重要部位的加快運(yùn)行速度的補(bǔ)丁通常不會(huì)被合并到Python內(nèi)。所以很多認(rèn)為Python很慢。不過(guò),根據(jù)二八定律,大多數(shù)程序?qū)λ俣纫蟛桓摺T谀承?duì)運(yùn)行速度要求很高的情況,Python程序員傾向于使用JIT技術(shù),或者用使用C/C++語(yǔ)言改寫這部分程序。目前可用的JIT技術(shù)是Pysco。Cython可以將Python代碼轉(zhuǎn)換成C代碼。

相對(duì)于Lisp這種傳統(tǒng)的函數(shù)式編程語(yǔ)言,Python對(duì)函數(shù)式編程只提供了有限的支持。有兩個(gè)標(biāo)準(zhǔn)庫(kù)(functools, itertools)提供了Haskell和Standard ML中久經(jīng)考驗(yàn)的函數(shù)式編程工具。

雖然Python可能被粗略地分類為「腳本語(yǔ)言」(script language),但實(shí)際上一些大規(guī)模軟件開發(fā)計(jì)劃例如Zope、Mnet及BitTorrent,Google也廣泛地使用它。Python的支持者較喜歡稱它為一種高階動(dòng)態(tài)編程語(yǔ)言,原因是「腳本語(yǔ)言」泛指僅作簡(jiǎn)單編程任務(wù)的語(yǔ)言,如shell script、JavaScript等只能處理簡(jiǎn)單任務(wù)的編程語(yǔ)言,並不能與Python相提并論。

Python本身被設(shè)計(jì)為可擴(kuò)展的。并非所有的特性和功能都集成到語(yǔ)言核心。可以使用C語(yǔ)言、C++、Cython來(lái)編寫擴(kuò)展模塊。Python解釋器本身也可以被集成到其它需要腳本語(yǔ)言的程序內(nèi)。因此,很多人還把Python作為一種「膠水語(yǔ)言」(glue language)使用。使用Python將其他語(yǔ)言編寫的程序進(jìn)行集成和封裝。在Google內(nèi)部的很多項(xiàng)目使用C++編寫性能要求極高的部分,然后用Python調(diào)用相應(yīng)的模塊。

Python的特點(diǎn):

1、第一行是特殊形式的注釋:它被稱作 組織行 ——源文件的頭兩個(gè)字符是#!,后面跟著一個(gè)程序。這行告訴你的Linux/Unix系統(tǒng)當(dāng)你 執(zhí)行 你的程序的時(shí)候,它應(yīng)該運(yùn)行哪個(gè)解釋器。建議使用這種形式——#!/usr/bin/env python,而不是——#!/usr/bin/python。

2、縮進(jìn)很重要。Python使用縮進(jìn)而不是一對(duì)花括號(hào)來(lái)劃分語(yǔ)句塊。

3、關(guān)鍵參數(shù)的概念很有用

4、None 返回"沒有任何東西",每一個(gè)函數(shù)默認(rèn)返回None

5、pass 空語(yǔ)句塊

6、文檔字符串,__doc__,沒多大用。但是一個(gè)好的Python程序,應(yīng)該要有文檔字符串,且一般遵循:“文檔字符串的慣例是一個(gè)多行字符串,它的首行以大寫字母開始,句號(hào)結(jié)尾。第二行是空行,從第三行開始是詳細(xì)的描述。 ”

6、python中引入模塊后(import)首先就要執(zhí)行模塊的主塊,當(dāng)然模塊中可能全是函數(shù)。如果要避免使用模塊名稱:from 模塊名 import 符號(hào)名,那麼使用該符號(hào)名就不用使用模塊名+點(diǎn)號(hào)+符號(hào)名,但是不推薦,容易造成程序不容易讀,而且容易出錯(cuò)(特別是在python簡(jiǎn)潔而簡(jiǎn)單的語(yǔ)法的基礎(chǔ)上) import... as ... 起一個(gè)別名

7、模塊的__name__屬性,相當(dāng)有用,解決了import的缺點(diǎn),可以實(shí)現(xiàn)如果不是運(yùn)行的本模塊而被調(diào)用,不調(diào)用主塊

#!/usr/bin/env python# Filename: using_name.pyif __name__ == '__main__':print 'This program is being run by itself'else:print 'I am being imported from another module'

8、刪除一個(gè)變量/名稱,你將無(wú)法再使用該變量——它就好像從來(lái)沒有存在過(guò)一樣。

9、可以使用內(nèi)建的dir函數(shù)來(lái)列出模塊定義的標(biāo)識(shí)符。標(biāo)識(shí)符有函數(shù)、類和變量。當(dāng)你為dir()提供一個(gè)模塊名的時(shí)候,它返回模塊定義的名稱列表。如果不提供參數(shù),它返回當(dāng)前模塊中定義的名稱列表

10、元組語(yǔ)法與list相似,意義相當(dāng)于枚舉,可以為空,如果只含有一個(gè)元素,需要加逗號(hào)以區(qū)別于表達(dá)式(“one”, )

11、元組最通常的用法是用在打印語(yǔ)句中,可以使用格式控制符

#!/usr/bin/env python# Filename: print_tuple.pyage = 22name = 'Swaroop'print '%s is %d years old' % (name, age)print 'Why is %s playing with that python?' % name

12、有一個(gè)內(nèi)建的字典類型,但是沒有沖突的解決方案,但這確實(shí)是字典的定義,想要更好的結(jié)構(gòu)就自己實(shí)現(xiàn)吧。語(yǔ)法:{key:value, key1:value1,...}

13、序列的概念:列表、元組和字符串都是序列,支持索引操作符和切片操作符。索引操作符讓我們可以從序列中抓取一個(gè)特定項(xiàng)目。切片操作符讓我們能夠獲取序列的一個(gè)切片,即一部分序列。索引可以是負(fù)數(shù),在那樣的情況下,位置是從序列尾開始計(jì)算的。序列的神奇之處在于你可以用相同的方法訪問元組、列表和字符串。

14、如果你想要復(fù)制一個(gè)列表或者類似的序列或者其他復(fù)雜的對(duì)象(不是如整數(shù)那樣的簡(jiǎn)單 對(duì)象 ),那么你必須使用切片操作符來(lái)取得拷貝。如果你只是想要使用另一個(gè)變量名,兩個(gè)名稱都 參考 同一個(gè)對(duì)象,那么如果你不小心的話,可能會(huì)引來(lái)各種麻煩。[淺拷貝和深拷貝的關(guān)系]

15、str類有很多方法,如果要非常熟悉str的操作,參考help(str)

16、剩下的就是掌握很多系統(tǒng)庫(kù)了,這個(gè)要靠經(jīng)驗(yàn),比如說(shuō)os.system(命令)可用于執(zhí)行shell命令,了解的庫(kù)越多,python就會(huì)讓你完成更強(qiáng)大的功能。

17、接下來(lái)是面向?qū)ο?,基本概念一樣,this由代替self, 而且這個(gè)名字不一定要寫成self,任何名字都可以,這也帶來(lái)了一個(gè)缺點(diǎn),你必須在形參里面指定,調(diào)用函數(shù)時(shí)不用傳遞該參數(shù)。

構(gòu)造函數(shù):__init__(self, ......)

析構(gòu)函數(shù):__del__ 對(duì)象滅亡時(shí)或者調(diào)用del時(shí)被調(diào)用

Python中所有的類成員(包括數(shù)據(jù)成員)都是公共的 ,所有的方法都是有效的 。只有一個(gè)例外:如果你使用的數(shù)據(jù)成員名稱以 雙下劃線前綴 比如__privatevar,Python的名稱管理體系會(huì)有效地把它作為私有變量。

支持多重繼承

18、如果你已經(jīng)厭煩了java、c++的讀寫文件,那么python會(huì)讓你重新喜歡上文件讀寫,python主張解決問題的方案越少越好,寫文件就一個(gè)f = file(name, 'w'),f.write(...)讀文件也一樣,f = file(name),f.read或readline,最后close

19、cPickle和pickle是叫做存儲(chǔ)器的重要模塊,可以非常方便地將一個(gè)對(duì)象存儲(chǔ)到一個(gè)文件,然后再取存儲(chǔ)從文件中取出來(lái)pickle.dump(object, file object),構(gòu)造對(duì)象時(shí),pickle.load(file object) [儲(chǔ)存、取存儲(chǔ)]

20、異常:raise,except,try...finally

21、sys模塊和os模塊有很多強(qiáng)大功能。

22、在函數(shù)中接收元組和列表當(dāng)要使函數(shù)接收元組或字典形式的參數(shù)的時(shí)候,有一種特殊的方法,它分別使用*和**前綴。這種方法在函數(shù)需要獲取可變數(shù)量的參數(shù)的時(shí)候特別有用。

23、lambda形式:lambda語(yǔ)句被用來(lái)創(chuàng)建新的函數(shù)對(duì)象,并且在運(yùn)行時(shí)返回它們。lambda語(yǔ)句用>來(lái)創(chuàng)建函數(shù)對(duì)象。本質(zhì)上,lambda需要一個(gè)參數(shù),后面僅跟單個(gè)表達(dá)式作為函數(shù)體,而表達(dá)式的值被這個(gè)新建的函數(shù)返回。注意,即便是print語(yǔ)句也不能用在lambda形式中,只能使用表達(dá)式。

24、exec、eval、assert、repr函數(shù)和反引號(hào)用來(lái)獲取對(duì)象的可打印的表示形式。你可以通過(guò)定義類的__repr__方法來(lái)控制你的對(duì)象在被repr函數(shù)調(diào)用的時(shí)候返回的內(nèi)容。

更多信息請(qǐng)查看IT技術(shù)專欄

更多信息請(qǐng)查看網(wǎng)絡(luò)編程
易賢網(wǎng)手機(jī)網(wǎng)站地址:如何編寫Python腳本替換文件中的多行字符?
由于各方面情況的不斷調(diào)整與變化,易賢網(wǎng)提供的所有考試信息和咨詢回復(fù)僅供參考,敬請(qǐng)考生以權(quán)威部門公布的正式信息和咨詢?yōu)闇?zhǔn)!

2025國(guó)考·省考課程試聽報(bào)名

  • 報(bào)班類型
  • 姓名
  • 手機(jī)號(hào)
  • 驗(yàn)證碼
關(guān)于我們 | 聯(lián)系我們 | 人才招聘 | 網(wǎng)站聲明 | 網(wǎng)站幫助 | 非正式的簡(jiǎn)要咨詢 | 簡(jiǎn)要咨詢須知 | 新媒體/短視頻平臺(tái) | 手機(jī)站點(diǎn) | 投訴建議
工業(yè)和信息化部備案號(hào):滇ICP備2023014141號(hào)-1 云南省教育廳備案號(hào):云教ICP備0901021 滇公網(wǎng)安備53010202001879號(hào) 人力資源服務(wù)許可證:(云)人服證字(2023)第0102001523號(hào)
云南網(wǎng)警備案專用圖標(biāo)
聯(lián)系電話:0871-65099533/13759567129 獲取招聘考試信息及咨詢關(guān)注公眾號(hào):hfpxwx
咨詢QQ:1093837350(9:00—18:00)版權(quán)所有:易賢網(wǎng)
云南網(wǎng)警報(bào)警專用圖標(biāo)