Python實(shí)現(xiàn)判斷一行代碼是否為注釋的方法
目前的編輯器大都可以自動檢測某一行代碼是否為代碼行或注釋行,但并不太提供代碼行/注釋行行數(shù)的統(tǒng)計(jì),對于大量代碼文件的代碼行/注釋行統(tǒng)計(jì),就更少見一些。本篇文章試用一段Python腳本來實(shí)現(xiàn)這一目標(biāo),并希望可以兼容統(tǒng)計(jì)不同語言編寫的代碼。
注釋符號的研究
我們先來關(guān)注常見語言的注釋符號構(gòu)成。一般來講注釋符號分為單行注釋符和多行注釋符,以Python為例,則分別為#和'''(或""")。由于多行注釋符會影響后續(xù)行的判斷,所以在遍歷各行時(shí)必須存在一個標(biāo)志位multiCmtFlagIdx,來記錄是否已經(jīng)開始多行注釋,以及多行注釋的符號為哪一種。有了該判斷之后,才可以繼續(xù)對后續(xù)的字符進(jìn)行分析。
1. 在多行注釋中
這種情況后面的分析較為簡單,由于已知多行注釋符的類型,我們可以判斷后續(xù)的字符中最早出現(xiàn)對應(yīng)的多行注釋結(jié)束符的位置為:
如果可以搜索到,則將multiCmtFlagIdx賦值為-1,表示多行注釋已經(jīng)結(jié)束。如果沒有搜索到,則說明本行后續(xù)字符仍在多行注釋中,可以直接開始下一行的解析。
2. 不在多行注釋中
對于這種情況,如果后續(xù)字符中除了空格和制表符,首先出現(xiàn)的是單行注釋符,則注釋符后面的字符都在注釋中,所以可以直接結(jié)束本行的解析,開始下一行。否則,我們需要繼續(xù)搜索多行注釋開始符出現(xiàn)的位置。
找到多行注釋開始符后,并不意味著后面就是注釋內(nèi)容,還需要做兩點(diǎn)檢查:
1)該注釋符是否在引號對中,因?yàn)榇藭r(shí)在引號中的注釋符是不起作用的;
2)該注釋符是否是最早出現(xiàn)的多行注釋開始符類型,由于同一種語言的多行注釋符可能有多種,而只有最早出現(xiàn)的多行注釋開始符才起作用。
1)針對第一點(diǎn),我們可以在搜索的起點(diǎn)到該注釋符的區(qū)間內(nèi)計(jì)算引號的數(shù)量,如果引號為偶數(shù),則說明不在引號對中,否則在引號對中。
引號數(shù)量奇偶性判斷,需要逐對來判斷,這是因?yàn)橐枌χ械囊柺遣黄鹱饔玫?。有一種特例是,多行注釋符同時(shí)也是引號的組合,例如Python。此時(shí)計(jì)算數(shù)量的引號,需要與搜索到的多行注釋符不同,如多行注釋符為''',則應(yīng)該計(jì)算"的數(shù)量。
2)針對第二點(diǎn),我們可以遍歷各個多行注釋開始符,并取位置最靠前的開始符,然后查找對應(yīng)的結(jié)束符。
代碼實(shí)現(xiàn)
\# encoding: utf-8
import re
'''
isCmt
功能:判斷一行字符串是否為注釋
輸入:
line: 字符串行
isInMultiCmt:前面一行是否在多行注釋中
qttnFlagList: 引號列表
輸出:
isCmt: 當(dāng)前行是否為注釋
isInMultiCmt:當(dāng)前行是否在多行注釋中
'''
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 #沒有找到多行注釋開始符,繼續(xù)查找下個類型的符號
if minStartIdx != len(line): #此時(shí)搜索到了多行注釋開始符
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('\*', '*')) #查找多汗注釋結(jié)束符的位置
multiCmtFlagIdx = -1
except:
break
# print isCmtRet, multiCmtFlagIdx
return isCmtRet, multiCmtFlagIdx #返回是否注釋行,以及當(dāng)前是否在多行注釋中
'''
函數(shù)名:isInQuotation
功能:根據(jù)字符串中引號的奇偶,判斷后面的字符是否在引號中
輸入:
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]: #排除引號同時(shí)也是注釋符號的情況
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: #根據(jù)最早出現(xiàn)的左引號,確認(rèn)左引號類型
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實(shí)現(xiàn)判斷一行代碼是否為注釋的方法就是小編分享給大家的全部內(nèi)容了,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
從零開始的TensorFlow+VScode開發(fā)環(huán)境搭建的步驟(圖文)
這篇文章主要介紹了從零開始的TensorFlow+VScode開發(fā)環(huán)境搭建的步驟(圖文),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-08-08
pytorch使用horovod多gpu訓(xùn)練的實(shí)現(xiàn)
這篇文章主要介紹了pytorch使用horovod多gpu訓(xùn)練的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09
python實(shí)現(xiàn)定制交互式命令行的方法
這篇文章主要介紹了python實(shí)現(xiàn)定制交互式命令行的方法,需要的朋友可以參考下2014-07-07
python實(shí)現(xiàn)tail實(shí)時(shí)查看服務(wù)器日志示例
今天小編就為大家分享一篇python實(shí)現(xiàn)tail實(shí)時(shí)查看服務(wù)器日志示例,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-12-12
PyTorch一小時(shí)掌握之神經(jīng)網(wǎng)絡(luò)氣溫預(yù)測篇
這篇文章主要介紹了PyTorch一小時(shí)掌握之神經(jīng)網(wǎng)絡(luò)氣溫預(yù)測篇,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-09-09
tensorboard 可視化之localhost:6006不顯示的解決方案
這篇文章主要介紹了tensorboard 可視化之localhost:6006不顯示的解決方案,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-05-05

