使用go實現(xiàn)刪除sql里面的注釋和字符串功能(demo)
項目里面有一個需求,要對sql進(jìn)行簡單的語法分析
為了避免sql里面的字符串和注釋對語法分析做干擾,我寫了一個java函數(shù),對sql進(jìn)行修剪,刪除里面字符串和注釋,用空格代替
周末閑著沒事,我用go重新實現(xiàn)了這個功能,感覺應(yīng)該會有后來人可以用上
說明:
sql里面的注釋有兩種單行注釋和多行注釋,其中單行注釋以--開頭,以\n結(jié)尾,多行注釋以/開頭,以/結(jié)尾
sql字符串是以'開頭,'結(jié)尾,但特別的地方是連續(xù)兩個單引號是代表一個單引號而不是字符串結(jié)束標(biāo)志
關(guān)鍵函數(shù)如下:
` /** 將字節(jié)數(shù)組里面注釋和字符串,用空格替換 rangeBeg和rangeEnd是數(shù)組元素起始位置 左閉右開 */ func TrimSqlByteArray(sql []byte, rangeBeg int, rangeEnd int) []byte { sqlLength := rangeEnd - rangeBeg - 1; //刪除注釋或者字符串后 用空格填充 必免因刪除導(dǎo)致粘連改變sql語義 const chPad = ' ' //結(jié)果切片,預(yù)分配空間為入?yún)ql長度一半 result := make([] byte, 0, sqlLength / 2) //本字符類型 var charType int = NORMAL; for i := rangeBeg; i < rangeEnd; i++ { /* *utf8編碼不影響判斷 //跳過非英文字符 if sql[i] & 0x80 != 0 { //utf8編碼:UTF-8是一種變長字節(jié)編碼方式。對于某一個字符的UTF-8編碼,如果只有一個字節(jié)則其最高二進(jìn)制位為0; //如果是多字節(jié),其第一個字節(jié)從最高位開始,連續(xù)的二進(jìn)制位值為1的個數(shù)決定了其編碼的位數(shù),其余各字節(jié)均以10開頭。 //UTF-8最多可用到6個字節(jié)。 這里不考慮異常,因為go的字符串基本都是標(biāo)準(zhǔn)utf8編碼 i += getPreNotZeroCount(sql[i]) - 1 continue; } */
//本字符類型 預(yù)設(shè)為普通字符 charType = NORMAL ch := sql[i] //下一個字符 var chNext byte; chNext = getCharSafe(sql, rangeEnd, i + 1) //非有效sql內(nèi)容結(jié)束位置 endPos := 0 if ch == '-' && chNext == '-' { //單行注釋 charType = LINE //下標(biāo)移到非有效字符的最后 endPos = seekToNext(sql, i + 2, rangeEnd, charType) } else if ch == '/' && chNext == '*' { //多行注釋 charType = MULTI //下標(biāo)移到非有效字符的最后 endPos = seekToNext(sql, i + 2, rangeEnd, charType) } else if ch == '\'' { //字符串 charType = STRING //下標(biāo)移到非有效字符的最后 endPos = seekToNext(sql, i + 1, rangeEnd, charType) } //如果字符是非有效字符 則用空格代替 否則保持原樣 if charType == NORMAL { result = append(result, ch) } else { result = append(result, chPad) i = endPos - 1 }
} return result; } /**
獲取字符串或者注釋的右邊界位置(不包含)
rangeEnd是數(shù)組邊界 */ func seekToNext(sql []byte, begPos int, rangeEnd int, charType int) int { result := begPos; switch charType { case MULTI: for ; result < rangeEnd; result++ { ch := sql[result] chNext := getCharSafe(sql, rangeEnd, result+ 1)
if ch == '*' && chNext == '/' { result = result + 1; break; } } break
case LINE: for ; result < rangeEnd; result++ { ch := sql[result]
if ch == '\n' { break; } } break
case STRING: for ; result < rangeEnd; result++ { ch := sql[result] chNext := getCharSafe(sql, rangeEnd, result + 1)
//sql字符串里面連續(xù)的單引號被認(rèn)為是' 則不是字符串結(jié)束標(biāo)志 if ch == '\'' && chNext == '\'' { result = result + 1; continue; } else if ch == '\'' { break; } } break
default: break; } result++; return result; }
完整代碼及單元測試已上傳 https://github.com/kingstarer/kingstarer.git
到此這篇關(guān)于使用go實現(xiàn)刪除sql里面的注釋和字符串功能的文章就介紹到這了,更多相關(guān)go刪除sql注釋和字符串內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Go語言利用Unmarshal解析json字符串的實現(xiàn)
本文主要介紹了Go語言利用Unmarshal解析json字符串的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-05-05golang 40行代碼實現(xiàn)通用協(xié)程池
golang協(xié)程機制很方便的解決了并發(fā)編程的問題,但是協(xié)程并不是沒有開銷的,所以也需要適當(dāng)限制一下數(shù)量。這篇文章主要介紹了golang 40行代碼實現(xiàn)通用協(xié)程池,需要的朋友可以參考下2018-08-08Golang使用Docker進(jìn)行集成測試的示例詳解
集成測試需要解決外部依賴問題,如?MySQL、Redis、網(wǎng)絡(luò)等依賴,本文就來聊聊?Go?程序如何使用?Docker?來解決集成測試中外部依賴問題吧2023-07-07關(guān)于Go語言中特有的設(shè)計模式與實現(xiàn)方式講解
雖然Go語言沒有像其他語言那樣明確的設(shè)計模式,但在實踐中,開發(fā)者們?nèi)匀话l(fā)現(xiàn)了一些在Go語言中特別適用的設(shè)計模式和實現(xiàn)方式,本文就來和大家一一進(jìn)行講解2023-05-05