Python实现判断一行代码是否为注释的方法


Posted in Python onMay 23, 2018

目前的编辑器大都可以自动检测某一行代码是否为代码行或注释行,但并不太提供代码行/注释行行数的统计,对于大量代码文件的代码行/注释行统计,就更少见一些。本篇文章试用一段Python脚本来实现这一目标,并希望可以兼容统计不同语言编写的代码。

注释符号的研究

我们先来关注常见语言的注释符号构成。一般来讲注释符号分为单行注释符和多行注释符,以Python为例,则分别为#和'''(或""")。由于多行注释符会影响后续行的判断,所以在遍历各行时必须存在一个标志位multiCmtFlagIdx,来记录是否已经开始多行注释,以及多行注释的符号为哪一种。有了该判断之后,才可以继续对后续的字符进行分析。

1. 在多行注释中

这种情况后面的分析较为简单,由于已知多行注释符的类型,我们可以判断后续的字符中最早出现对应的多行注释结束符的位置为:

如果可以搜索到,则将multiCmtFlagIdx赋值为-1,表示多行注释已经结束。如果没有搜索到,则说明本行后续字符仍在多行注释中,可以直接开始下一行的解析。

2. 不在多行注释中

对于这种情况,如果后续字符中除了空格和制表符,首先出现的是单行注释符,则注释符后面的字符都在注释中,所以可以直接结束本行的解析,开始下一行。否则,我们需要继续搜索多行注释开始符出现的位置。

找到多行注释开始符后,并不意味着后面就是注释内容,还需要做两点检查:

1)该注释符是否在引号对中,因为此时在引号中的注释符是不起作用的;

2)该注释符是否是最早出现的多行注释开始符类型,由于同一种语言的多行注释符可能有多种,而只有最早出现的多行注释开始符才起作用。

1)针对第一点,我们可以在搜索的起点到该注释符的区间内计算引号的数量,如果引号为偶数,则说明不在引号对中,否则在引号对中。

引号数量奇偶性判断,需要逐对来判断,这是因为引号对中的引号是不起作用的。有一种特例是,多行注释符同时也是引号的组合,例如Python。此时计算数量的引号,需要与搜索到的多行注释符不同,如多行注释符为''',则应该计算"的数量。

2)针对第二点,我们可以遍历各个多行注释开始符,并取位置最靠前的开始符,然后查找对应的结束符。

代码实现

\# encoding: utf-8
import re
'''
isCmt
功能:判断一行字符串是否为注释
输入:
 line: 字符串行
 isInMultiCmt:前面一行是否在多行注释中
 qttnFlagList: 引号列表
输出:
 isCmt: 当前行是否为注释
 isInMultiCmt:当前行是否在多行注释中
'''
def isCmt(line, multiCmtFlagIdx, cmtFlagObj):
 singleCmtFlag = cmtFlagObj["singleCmtFlag"] #单行注释符号
 multiCmtFlagList =cmtFlagObj["multiCmtFlagList"]
 qttnFlagList = cmtFlagObj["qttnFlagList"] #引号列表
 startPos = 0 #搜索多行注释符的开始位置
 isCmtRet = True
 # print 'line: ' + line.strip()
 while startPos < len(line): #查找注释符号直到行末
  if multiCmtFlagIdx == -1: #不在多行注释中
   minStartIdx = len(line) #搜索到最靠前的多行注释符
   if singleCmtFlag != '' and re.match(r'(\s)*' + singleCmtFlag, line[startPos:]): #单行注释
    break
   idx = 0
   preStartIdx = startPos #记录搜索多行注释符前的搜索位置
   while idx < len(cmtFlagObj["multiCmtFlagList"]):
    startCmtFlag = cmtFlagObj["multiCmtFlagList"][idx][0] #多行注释开始符号
    if startCmtFlag == '':
     return False, -1 #无多行注释符号
    try:
     startPos = re.search(r'(?<!\\)' + startCmtFlag, line[startPos:]).start() + startPos #找到多行注释开始符号
     if isInQuotation(line[:startPos], startCmtFlag, qttnFlagList): #注释开始符在引号中
      startPos += len(startCmtFlag.replace('\*', '*')) #找下一个多行注释开始符
      continue
     else: #注释符号不在引号中
      startPos += len(startCmtFlag.replace('\*', '*'))
      if startPos < minStartIdx:
       multiCmtFlagIdx = idx #是多行注释
       minStartIdx = startPos
      startPos = preStartIdx #找下一个多行注释开始符
      idx += 1
    except:
     idx += 1
     continue #没有找到多行注释开始符,继续查找下个类型的符号
   if minStartIdx != len(line): #此时搜索到了多行注释开始符
    startCmtFlag = cmtFlagObj["multiCmtFlagList"][multiCmtFlagIdx][0]
    if not re.match(r'(\s)*' + startCmtFlag, line[preStartIdx:]):
     isCmtRet = False
   elif line[preStartIdx:] != '\n':
    isCmtRet = False
   startPos = minStartIdx
  elif multiCmtFlagIdx != -1: #在多行注释中
   endCmtFlag = cmtFlagObj["multiCmtFlagList"][multiCmtFlagIdx][1] #多行注释开始符
   if endCmtFlag == '':
    return False, -1 #注释符号配置有错误
   try:
    startPos \
    = re.search(endCmtFlag, line[startPos:]).start() \
    + startPos \
    + len(endCmtFlag.replace('\*', '*')) #查找多汗注释结束符的位置
    multiCmtFlagIdx = -1
   except:
    break
 # print isCmtRet, multiCmtFlagIdx
 return isCmtRet, multiCmtFlagIdx #返回是否注释行,以及当前是否在多行注释中
'''
函数名:isInQuotation
功能:根据字符串中引号的奇偶,判断后面的字符是否在引号中
输入:
 line: 一行代码中指定字符前的字符串
 qttnFlagList: 引号列表
输出:
 布尔值:
  True:字符串包含在引号中
  False:字符串不包含在引号中
'''
def isInQuotation(line, cmtFlag, qttnFlagList):
 qttnFlagIdx = len(line)
 flagIdx = len(line)
 rearLine = line
 for i in range(len(qttnFlagList)):
  flag = qttnFlagList[i]
  if flag == cmtFlag[0]: #排除引号同时也是注释符号的情况
   continue
  try:
   flagIdx = re.search(r'(?<!\\)' + flag + r'.*', line).start() #查找左引号
   rearLine = re.search(r'(?<!\\)' + flag + r'.*', line).group()[len(flag):]
  except:
   flagIdx = len(line)
  if flagIdx < qttnFlagIdx: #根据最早出现的左引号,确认左引号类型
   qttnFlagIdx = flagIdx
   qttnFlag = flag
 if qttnFlagIdx != len(line):
  try:
   #print rearLine
   rearLine = re.search(r'(?<!\\)' + qttnFlag + r'.*', rearLine).group()[len(qttnFlag):] #查找右引号
   return isInQuotation(rearLine, cmtFlag[0], qttnFlagList) #再次查找下一个左引号
  except:
   return True #在引号对中
 else:
  return False #不在引号对中

以上这篇Python实现判断一行代码是否为注释的方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python中使用glob和rmtree删除目录子目录及所有文件的例子
Nov 21 Python
浅谈numpy中linspace的用法 (等差数列创建函数)
Jun 07 Python
python实现随机森林random forest的原理及方法
Dec 21 Python
python matlibplot绘制3D图形
Jul 02 Python
python实现字符串中字符分类及个数统计
Sep 28 Python
对Python之gzip文件读写的方法详解
Feb 08 Python
python中with语句结合上下文管理器操作详解
Dec 19 Python
Pyspark读取parquet数据过程解析
Mar 27 Python
Python如何实现自带HTTP文件传输服务
Jul 08 Python
python批量提取图片信息并保存的实现
Feb 05 Python
解决import tensorflow导致jupyter内核死亡的问题
Feb 06 Python
Python中rapidjson参数校验实现
Jul 25 Python
对python的文件内注释 help注释方法
May 23 #Python
Python基于生成器迭代实现的八皇后问题示例
May 23 #Python
Pycharm 操作Django Model的简单运用方法
May 23 #Python
PyCharm代码格式调整方法
May 23 #Python
创建pycharm的自定义python模板方法
May 23 #Python
对Python中9种生成新对象的方法总结
May 23 #Python
使用pycharm生成代码模板的实例
May 23 #Python
You might like
php 图片上传类代码
2009/07/17 PHP
PHP 获取MSN好友列表的代码(2009-05-14测试通过)
2009/09/09 PHP
用php实现的获取网页中的图片并保存到本地的代码
2010/01/05 PHP
PHP中怎样保持SESSION不过期 原理及方案介绍
2013/08/08 PHP
学习php过程中的一些注意点的总结
2013/10/25 PHP
在Yii框架中使用PHP模板引擎Twig的例子
2014/06/13 PHP
Linux环境下php实现给网站截图的方法
2016/05/03 PHP
php+MySQL实现登录时验证登录名和密码是否正确
2016/05/10 PHP
ThinkPHP实现图片上传操作的方法详解
2017/05/08 PHP
基于Laravel 多个中间件的执行顺序详解
2019/10/21 PHP
date.parse在IE和FF中的区别
2010/07/29 Javascript
JavaScript中this关键词的使用技巧、工作原理以及注意事项
2014/05/20 Javascript
Node.js中HTTP模块与事件模块详解
2014/11/14 Javascript
BootStrap中Tab页签切换实例代码
2016/05/30 Javascript
js传值后台中文出现乱码的解决方法
2016/06/30 Javascript
Zabbix添加Node.js监控的方法
2016/10/20 Javascript
bootstrap 表单验证使用方法
2017/01/11 Javascript
jQuery插件FusionCharts绘制的3D双柱状图效果示例【附demo源码】
2017/04/20 jQuery
Vue+Koa2+mongoose写一个像素绘板的实现方法
2019/09/10 Javascript
Vue 中使用lodash对事件进行防抖和节流操作
2020/07/26 Javascript
[06:04]DOTA2国际邀请赛纪录片:Just For LGD
2013/08/11 DOTA
[02:44]DOTA2英雄基础教程 魅惑魔女
2014/01/07 DOTA
[02:46]解说DC:感谢430陪伴我们的DOTA2国际邀请赛岁月
2016/06/29 DOTA
python脚本爬取字体文件的实现方法
2017/04/29 Python
详解Python中正则匹配TAB及空格的小技巧
2019/07/26 Python
pygame实现打字游戏
2021/02/19 Python
尤妮佳moony海外旗舰店:日本殿堂级纸尿裤品牌
2018/02/23 全球购物
Dr. Martens马汀博士德国官网:马丁靴鼻祖
2019/12/26 全球购物
中软Java笔试题
2012/11/11 面试题
JAVA程序员面试题
2012/10/03 面试题
师范毕业生自我鉴定
2014/01/15 职场文书
信息服务专业毕业生求职信
2014/03/02 职场文书
美术指导助理求职信
2014/04/20 职场文书
债务纠纷代理词
2015/05/25 职场文书
合作意向书怎么写
2019/06/24 职场文书
《传颂之物 虚伪的假面》BD发售宣传CM公开
2022/04/04 日漫