python文本替换脚本_如何编写Python脚本替换文件中的多行字符?
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
python⽂本替换脚本_如何编写Python脚本替换⽂件中的多⾏
字符?
《派森》(Python)3.13 win32 英⽂安装版
类型:编程⼯具⼤⼩:21M语⾔:英⽂ 评分:8.7
标签:
⽴即下载
在⼤概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.pyimportos, sys, fileinput#-------------------------------------------------------------defusage():printu'''help: comment.py
[dirname]: Option, select a directory to operate
[filename]: Option, select a file to operate
Example: python comment.py /home/saylor/test'''#--------------------------------------------------------------defcommentFile(src, fileList):'''description: comment files
param src: Operate file name'''#if file exist?ifnotos.path.exists(src):print'Error: file - %s doesn\'t exist.'% srcreturnFalseifos.path.islink(src):print'Error: file - %s is just a link, will not handle it.'returnFalse
filetype=(os.path.splitext(src))[1]ifnotfiletypein['.c','.h']:returnFalsetry:ifnotos.access(src, os.W_OK):
os.chmod(src,0664)except:print'Error: you can not chang %s\'s mode.'% srctry:
inputf=open(src,'r')
outputfilename=src+'.tmp'outputf=open(outputfilename,'w')
beginLine=0
endLine=100000000isMatched=False#-----find the beginLine and endLine -------------------
foreachlineinfileinput.input(src):ifeachline.find('/*')>=0:
beginLine=fileinput.lineno()ifeachline.find('Copyright 2002 Sun Microsystems, Inc. All rights reserved.')>=0:
isMatched=Trueifeachline.find('*/')>=0andisMatched:
endLine=fileinput.lineno()break#-----delete the content between beginLine and endLine-----printbeginLine, endLine
lineNo=1foreachlineininputf:iflineNo
outputf.write(eachline)eliflineNo>endLine:printeachline
outputf.write(eachline)
lineNo=lineNo+1inputf.close()
outputf.close()
os.rename(outputfilename, src)
fileList.append(src)except:print'Error: unexcept error.'inputf.close()
outputf.close()returnTrue#--------------------------------------------------------------defcommentDir(src, fileList):'''description:
comment files in src(dir)
param src:
operate files in src(dir)'''#if dir exist?ifnotos.path.exists(src):print'Error: dir - %s is not exist.'%s (src)returnFalse
filelists=os.listdir(src)foreachfileinfilelists:
eachfile=src+'/'+eachfileifos.path.isdir(eachfile):
commentDir(eachfile, fileList)elifos.path.isfile(eachfile):
commentFile(eachfile, fileList)returnTrue#--------------------------------------------------------------defmain():iflen(sys.argv)<2:
usage()
sys.exit(1)
src=sys.argv[1]ifos.path.isdir(src):
dire=os.path.abspath(src)
dirFlag=Trueelifos.path.isfile(src):
fl=os.path.abspath(src)
dirFlag=Falseelse:print'Error'fileList=[]ifdirFlag:
commentDir(dire, fileList)else:
commentFile(fl, fileList)iffileList:print'Successful handle file: ...'foreachfileinfileList:printeachfileprint'Done'returnTrue#--------------------------------------------------------------if__name__=='__main__':
main()
4、Python的特点
Python⼊门我强烈推荐下⾯的资料,深⼊学习请阅读其它资料:
Python的设计哲学是“优雅”、“明确”、“简单”。
因此,Perl语⾔中“总有多种⽅法来做同⼀件事”的理念在Python开发者中通常是难以忍受的。
Python开发者的哲学是“⽤⼀种⽅法,最好是只有⼀种⽅法来做⼀件事”。
在设计Python语⾔时,如果⾯临多种选
择,Python开发者总会拒绝花哨的语法,⽽选择明确的没有或者很少有歧义的语法。
由于这种设计观念的差异,Python源代码通常认为⽐Perl具备更好的可读性。
Python开发⼈员尽量避开不成熟或者不重要的优化。
⼀些针对⾮重要部位的加快运⾏速度的补丁通常不会被合并到Python内。
所以很多认为Python很慢。
不过,根据⼆⼋定律,⼤多数程序对速度要求不⾼。
在某些对运⾏速度要求很⾼的情况,Python程序员倾向于使⽤JIT技术,或者⽤使⽤C/C++语⾔改写这部分程序。
⽬前可⽤的JIT技术是Pysco。
Cython可以将Python代码转换成C代码。
相对于Lisp这种传统的函数式编程语⾔,Python对函数式编程只提供了有限的⽀持。
有两个标准库(functools, itertools)提供了Haskell和Standard ML中久经考验的函数式编程⼯具。
虽然Python可能被粗略地分类为「脚本语⾔」(script language),但实际上⼀些⼤规模软件开发计划例如Zope、Mnet及
BitTorrent,Google也⼴泛地使⽤它。
Python的⽀持者较喜欢称它为⼀种⾼阶动态编程语⾔,原因是「脚本语⾔」泛指仅作简单编程任务的语⾔,如shell script、JavaScript等只能处理简单任务的编程语⾔,並不能与Python相提并论。
Python本⾝被设计为可扩展的。
并⾮所有的特性和功能都集成到语⾔核⼼。
可以使⽤C语⾔、C++、Cython来编写扩展模块。
Python解释器本⾝也可以被集成到其它需要脚本语⾔的程序内。
因此,很多⼈还把Python作为⼀种「胶⽔语⾔」(glue language)使⽤。
使⽤Python将其他语⾔编写的程序进⾏集成和封装。
在Google内部的很多项⽬使⽤C++编写性能要求极⾼的部分,然后⽤Python调⽤相应的模块。
Python的特点:
1、第⼀⾏是特殊形式的注释:它被称作 组织⾏ ——源⽂件的头两个字符是#!,后⾯跟着⼀个程序。
这⾏告诉你的Linux/Unix系统当你 执⾏ 你的程序的时候,它应该运⾏哪个解释器。
建议使⽤这种形式——#!/usr/bin/env python,⽽不是——#!/usr/bin/python。
2、缩进很重要。
Python使⽤缩进⽽不是⼀对花括号来划分语句块。
3、关键参数的概念很有⽤
4、None 返回"没有任何东西",每⼀个函数默认返回None
5、pass 空语句块
6、⽂档字符串,__doc__,没多⼤⽤。
但是⼀个好的Python程序,应该要有⽂档字符串,且⼀般遵循:“⽂档字符串的惯例是⼀个多⾏字符串,它的⾸⾏以⼤写字母开始,句号结尾。
第⼆⾏是空⾏,从第三⾏开始是详细的描述。
”
6、python中引⼊模块后(import)⾸先就要执⾏模块的主块,当然模块中可能全是函数。
如果要避免使⽤模块名称:from 模块名 import 符号名,那麽使⽤该符号名就不⽤使⽤模块名+点号+符号名,但是不推荐,容易造成程序不容易读,⽽且容易出错(特别是在python简洁⽽简单的语法的基础上) import... as ... 起⼀个别名
7、模块的__name__属性,相当有⽤,解决了import的缺点,可以实现如果不是运⾏的本模块⽽被调⽤,不调⽤主块
#!/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、删除⼀个变量/名称,你将⽆法再使⽤该变量——它就好像从来没有存在过⼀样。
9、可以使⽤内建的dir函数来列出模块定义的标识符。
标识符有函数、类和变量。
当你为dir()提供⼀个模块名的时候,它返回模块定义的名称列表。
如果不提供参数,它返回当前模块中定义的名称列表
10、元组语法与list相似,意义相当于枚举,可以为空,如果只含有⼀个元素,需要加逗号以区别于表达式(“one”, )
11、元组最通常的⽤法是⽤在打印语句中,可以使⽤格式控制符
#!/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、有⼀个内建的字典类型,但是没有冲突的解决⽅案,但这确实是字典的定义,想要更好的结构就⾃⼰实现吧。
语法:{key:value,
key1:value1,...}
13、序列的概念:列表、元组和字符串都是序列,⽀持索引操作符和切⽚操作符。
索引操作符让我们可以从序列中抓取⼀个特定项⽬。
切⽚操作符让我们能够获取序列的⼀个切⽚,即⼀部分序列。
索引可以是负数,在那样的情况下,位置是从序列尾开始计算的。
序列的神奇之处在于你可以⽤相同的⽅法访问元组、列表和字符串。
14、如果你想要复制⼀个列表或者类似的序列或者其他复杂的对象(不是如整数那样的简单 对象 ),那么你必须使⽤切⽚操作符来取得拷贝。
如果你只是想要使⽤另⼀个变量名,两个名称都 参考 同⼀个对象,那么如果你不⼩⼼的话,可能会引来各种⿇烦。
[浅拷贝和深拷贝的关系]
15、str类有很多⽅法,如果要⾮常熟悉str的操作,参考help(str)
16、剩下的就是掌握很多系统库了,这个要靠经验,⽐如说os.system(命令)可⽤于执⾏shell命令,了解的库越多,python就会让你完成更强⼤的功能。
17、接下来是⾯向对象,基本概念⼀样,this由代替self, ⽽且这个名字不⼀定要写成self,任何名字都可以,这也带来了⼀个缺点,你必须在形参⾥⾯指定,调⽤函数时不⽤传递该参数。
构造函数:__init__(self, ......)
析构函数:__del__ 对象灭亡时或者调⽤del时被调⽤
Python中所有的类成员(包括数据成员)都是公共的 ,所有的⽅法都是有效的 。
只有⼀个例外:如果你使⽤的数据成员名称以 双下划线前缀⽐如__privatevar,Python的名称管理体系会有效地把它作为私有变量。
⽀持多重继承
18、如果你已经厌烦了java、c++的读写⽂件,那么python会让你重新喜欢上⽂件读写,python主张解决问题的⽅案越少越好,写⽂件就⼀个f = file(name, 'w'),f.write(...)读⽂件也⼀样,f = file(name),f.read或readline,最后close
19、cPickle和pickle是叫做存储器的重要模块,可以⾮常⽅便地将⼀个对象存储到⼀个⽂件,然后再取存储从⽂件中取出来
pickle.dump(object, file object),构造对象时,pickle.load(file object) [储存、取存储]
20、异常:raise,except,try...finally
21、sys模块和os模块有很多强⼤功能。
22、在函数中接收元组和列表当要使函数接收元组或字典形式的参数的时候,有⼀种特殊的⽅法,它分别使⽤*和**前缀。
这种⽅法在函数需要获取可变数量的参数的时候特别有⽤。
23、lambda形式:lambda语句被⽤来创建新的函数对象,并且在运⾏时返回它们。
lambda语句⽤>来创建函数对象。
本质上,lambda需要⼀个参数,后⾯仅跟单个表达式作为函数体,⽽表达式的值被这个新建的函数返回。
注意,即便是print语句也不能⽤在lambda形式中,只能使⽤表达式。
24、exec、eval、assert、repr函数和反引号⽤来获取对象的可打印的表⽰形式。
你可以通过定义类的__repr__⽅法来控制你的对象在被repr函数调⽤的时候返回的内容。
最后,感谢实习所在公司给我⾜够的时间和机会去学习新的东西。
还有要感谢学习Python期间,编写参阅资料的⼈。
期间我参阅了下⾯的资料(包括上⾯推荐的资料):
Chinaunix的Python论坛资料
《OReilly-Learning-Python-4th-Edition-Oct-2009》
当然还有前⾯提到过的⼊门资料:简明 Python 教程(中),对应的英⽂版是A Byte of Python。