您好,登錄后才能下訂單哦!
這篇文章將為大家詳細講解有關如何使用Python實現判斷一行代碼是否為注釋,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。
目前的編輯器大都可以自動檢測某一行代碼是否為代碼行或注釋行,但并不太提供代碼行/注釋行行數的統計,對于大量代碼文件的代碼行/注釋行統計,就更少見一些。本篇文章試用一段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實現判斷一行代碼是否為注釋”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。