需求驱动学习之Python(如何编写Python脚本替换文件中的多行字符?)

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介:

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?
if not 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]
if not filetype in ['.c','.h']:
return False
try:
if not 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?
if not 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的特点

Python入门我强烈推荐下面的资料,深入学习请阅读其它资料:

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

《简明 Python 教程》http://woodpecker.org.cn/abyteofpython_cn/chinese/

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.py
    if __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.py
    age = 22
    name = '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期间,编写参阅资料的人。期间我参阅了下面的资料(包括上面推荐的资料):

  • wiki:http://zh.wikipedia.org/zh/Python
  • Chinaunix的Python论坛资料
  • 《OReilly-Learning-Python-4th-Edition-Oct-2009》
  • 当然还有前面提到过的入门资料:简明 Python 教程(中),对于的英文版是A Byte of Python




本文转自吴秦博客园博客,原文链接:http://www.cnblogs.com/skynet/archive/2010/12/08/1900777.html,如需转载请自行联系原作者

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
1天前
|
Python
python pandas学习(一)
该代码段展示了四个主要操作:1) 删除指定列名,如商品id;2) 使用正则表达式模糊匹配并删除列,例如匹配订单商品名称1的列;3) 将毫秒级时间戳转换为带有时区调整的日期时间格式,并增加8小时以适应本地时区;4) 将列表转换为DataFrame后保存为Excel文件,文件路径和名称根据变量拼接而成。
12 3
|
11天前
|
机器学习/深度学习 存储 算法
解锁文件共享软件背后基于 Python 的二叉搜索树算法密码
文件共享软件在数字化时代扮演着连接全球用户、促进知识与数据交流的重要角色。二叉搜索树作为一种高效的数据结构,通过有序存储和快速检索文件,极大提升了文件共享平台的性能。它依据文件名或时间戳等关键属性排序,支持高效插入、删除和查找操作,显著优化用户体验。本文还展示了用Python实现的简单二叉搜索树代码,帮助理解其工作原理,并展望了该算法在分布式计算和机器学习领域的未来应用前景。
|
21天前
|
监控 网络安全 开发者
Python中的Paramiko与FTP文件夹及文件检测技巧
通过使用 Paramiko 和 FTP 库,开发者可以方便地检测远程服务器上的文件和文件夹是否存在。Paramiko 提供了通过 SSH 协议进行远程文件管理的能力,而 `ftplib` 则提供了通过 FTP 协议进行文件传输和管理的功能。通过理解和应用这些工具,您可以更加高效地管理和监控远程服务器上的文件系统。
51 20
|
25天前
|
安全 Linux 网络安全
利用Python脚本自动备份网络设备配置
通过本文的介绍,我们了解了如何利用Python脚本自动备份网络设备配置。该脚本使用 `paramiko`库通过SSH连接到设备,获取并保存配置文件。通过定时任务调度,可以实现定期自动备份,确保网络设备配置的安全和可用。希望这些内容能够帮助你在实际工作中实现网络设备的自动化备份。
51 14
|
27天前
|
存储 数据采集 数据处理
如何在Python中高效地读写大型文件?
大家好,我是V哥。上一篇介绍了Python文件读写操作,今天聊聊如何高效处理大型文件。主要方法包括:逐行读取、分块读取、内存映射(mmap)、pandas分块处理CSV、numpy处理二进制文件、itertools迭代处理及linecache逐行读取。这些方法能有效节省内存,提升效率。关注威哥爱编程,学习更多Python技巧。
|
28天前
|
存储 JSON 对象存储
如何使用 Python 进行文件读写操作?
大家好,我是V哥。本文介绍Python中文件读写操作的方法,包括文件读取、写入、追加、二进制模式、JSON、CSV和Pandas模块的使用,以及对象序列化与反序列化。通过这些方法,你可以根据不同的文件类型和需求,灵活选择合适的方式进行操作。希望对正在学习Python的小伙伴们有所帮助。欢迎关注威哥爱编程,全栈路上我们并肩前行。
|
1月前
|
存储 算法 Serverless
剖析文件共享工具背后的Python哈希表算法奥秘
在数字化时代,文件共享工具不可或缺。哈希表算法通过将文件名或哈希值映射到存储位置,实现快速检索与高效管理。Python中的哈希表可用于创建简易文件索引,支持快速插入和查找文件路径。哈希表不仅提升了文件定位速度,还优化了存储管理和多节点数据一致性,确保文件共享工具高效运行,满足多用户并发需求,推动文件共享领域向更高效、便捷的方向发展。
|
1月前
|
数据可视化 数据挖掘 大数据
1.1 学习Python操作Excel的必要性
学习Python操作Excel在当今数据驱动的商业环境中至关重要。Python能处理大规模数据集,突破Excel行数限制;提供丰富的库实现复杂数据分析和自动化任务,显著提高效率。掌握这项技能不仅能提升个人能力,还能为企业带来价值,减少人为错误,提高决策效率。推荐从基础语法、Excel操作库开始学习,逐步进阶到数据可视化和自动化报表系统。通过实际项目巩固知识,关注新技术,为职业发展奠定坚实基础。
|
2月前
|
Python
自动化微信朋友圈:Python脚本实现自动发布动态
本文介绍如何使用Python脚本自动化发布微信朋友圈动态,节省手动输入的时间。主要依赖`pyautogui`、`time`、`pyperclip`等库,通过模拟鼠标和键盘操作实现自动发布。代码涵盖打开微信、定位朋友圈、准备输入框、模拟打字等功能。虽然该方法能提高效率,但需注意可能违反微信使用条款,存在风险。定期更新脚本以适应微信界面变化也很重要。
213 61
|
4月前
|
存储 算法 API
Python学习五:函数、参数(必选、可选、可变)、变量、lambda表达式、内置函数总结、案例
这篇文章是关于Python函数、参数、变量、lambda表达式、内置函数的详细总结,包含了基础知识点和相关作业练习。
63 0

热门文章

最新文章

推荐镜像

更多