【Python实现删除目录里所有C源码的注释】

0前言

我老板之前演讲说了一个删除C工程里所有注释的方法,在实际工作中十分有用,他使用perl写的,很简洁,但是我不会,鉴于我会的脚本语言只有Python,所以打算自己写一个更加完善的

1完整复制整个工程

为了给自己留一个带注释的工程,同时也害怕程序突然出错,所以还是先完整复制整个工程目录,在新的目录里做文本处理。通过递归一级一级的复制文件,需要 import shutil

# 完整复制整个目录
def copy_dir(src_path, target_path):
    if not os.path.isdir(target_path):
        os.mkdir(target_path)
    filelist_src = os.listdir(src_path)#用于返回一个文件名和目录名
    for file in filelist_src:#遍历所有的文件或文件夹
        src_path_read_new =os.path.join(os.path.abspath(src_path),file)
        target_path_write_new = os.path.join(os.path.abspath(target_path),file)
        if os.path.isdir(src_path_read_new):#判断该读入路径是否是目录文件夹,如果是文件夹执行递归
            if not os.path.exists(target_path_write_new):#判断目标路径是否存在该文件夹
                os.mkdir(target_path_write_new)#没有就创建文件夹
            copy_dir(src_path_read_new,target_path_write_new)#递归
        else:#如果是文件,执行复制
            shutil.copy(src_path_read_new,target_path_write_new)

2使用正则表达式寻找目录里.c.h文件

传入目录名,返回该目录下的所有.c.h文件的绝对路径

# 找到一个目录里的所有.c .h文件
def find_dir(dir_name):
    file_list = []
    for path_name, dir, files_name in os.walk(dir_name):
        for file in files_name:
            if bool(re.search(".h|.c$", file)) != 0:
                file_list.append(os.path.join(path_name, file))
    return file_list

3 找到注释并用空字符替换

def treat_comment(file):
    bds0 = r'\/\/.*'  # 标准匹配单行注释
    bds1 = r'\/\*(?:[^\*]|\*+[^\/\*])*\*+\/'  # 标准匹配多行注释  可匹配跨行注释

    target0 = re.compile(bds0)  # 单行注释
    target = re.compile(bds1)  # 编译正则表达式

    # 注意编码,可加encoding,默认是gbk
    with open(file, 'r') as f:
        data = f.read()

    # 找出两种注释
    comment1 = target0.findall(data)
    comment2 = target.findall(data)

    # 此时已经找到了注释所在,接下来就是删除注释
    comment = comment1 + comment2
    for i in comment:
    	#这里非常关键,普通的替换,会将data里所有数据的i都找出来替换
    	# 第三个参数1控制其找到第一个匹配就替换,然后就结束了
        data = data.replace(i, '', 1)  # 替换为空字符串

    f = open(file, 'w')
    f.write(data)
    f.close()
data = data.replace(i, '', 1)  # 替换为空字符串

这里非常关键,普通的替换,会将data里所有数据的i都找出来替换掉,而第三个参数1控制其找到第一个匹配就替换,然后就结束了,这样就很好解决了一个问题:比如有这样一段注释

//
//printf("hello");

正则匹配到了'//' 和 '//printf("hello");', 那么不加参数1处理完一个循环之后变成


printf("hello");

再处理第二个循环时就会找'//printf("hello");'做替换, 结果就是data里已经没有了这个字符串,不会做任何处理,最终的结果就是留下了printf("hello");

4删除空白行

这里使用了正则和列表推导式

# 删除文件的行,这个行以空格开头(空格可能没有可能连续很多个)紧接着是\n
def remove_line(file):
    lines = [l for l in open(file, "r") if bool(re.search("^\s*\n", l)) == 0]
    # print(lines)
    fd = open(file, "w")
    fd.writelines(lines)
    fd.close()

5汇总使用

获取时间戳作为新目录名,sys.argv获取命令行执行时的参数列表

$ python test.py arg1 arg2 arg3
参数个数为: 4 个参数。
参数列表: ['test.py', 'arg1', 'arg2', 'arg3']
if __name__ == '__main__':
    # 旧的目录
    now_time = datetime.datetime.now().strftime("%Y-%m-%d %H-%M-%S")
    # old_dir = '.\\C_Project_demo'
    if len(sys.argv) == 1:
        old_dir = os.path.dirname(__file__)
    else:
        old_dir = sys.argv[1]
    new_dir = old_dir + '_new_' + now_time

    copy_dir(old_dir, new_dir)
    files = find_dir(new_dir)
    print(files)
    for file in files:
        treat_comment(file)
        # 删除新文件的空白行
        remove_line(file)

使用方法

上面所有方法放在一个文件里,假设取名为remove_comment.py

  1. remove_comment.py放在想要处理的工程里,双击即可在同级目录找到处理完成的目录
  2. 在命令行输入python 你的py文件路径 想要处理的工程目录
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值