咔叽网单游戏基地

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 25|回复: 0

[Golang] 使用go实现删除sql里面的注释和字符串功能(demo)

[复制链接]
  • TA的每日心情
    无聊
    2019-4-21 13:02
  • 签到天数: 3 天

    [LV.2]圆转纯熟

    2万

    主题

    2万

    帖子

    11万

    积分

    帖子管理员

    Rank: 9Rank: 9Rank: 9

    积分
    117124

    灌水之王最佳新人活跃会员热心会员宣传达人

    发表于 2020-12-19 14:56:34 | 显示全部楼层 |阅读模式
    项目里面有一个需求,要对sql进行简单的语法分析
    为了避免sql里面的字符串和注释对语法分析做干扰,我写了一个java函数,对sql进行修剪,删除里面字符串和注释,用空格代替
    周末闲着没事,我用go重新实现了这个功能,感觉应该会有后来人可以用上
    说明:
    sql里面的注释有两种单行注释和多行注释,其中单行注释以--开头,以\n结尾,多行注释以/开头,以/结尾
    sql字符串是以'开头,'结尾,但特别的地方是连续两个单引号是代表一个单引号而不是字符串结束标志
    关键函数如下:
    1. `
    2. /**
    3. 将字节数组里面注释和字符串,用空格替换 rangeBeg和rangeEnd是数组元素起始位置 左闭右开
    4. */
    5. func TrimSqlByteArray(sql []byte, rangeBeg int, rangeEnd int) []byte {
    6. sqlLength := rangeEnd - rangeBeg - 1;
    7. //删除注释或者字符串后 用空格填充 必免因删除导致粘连改变sql语义
    8. const chPad = ' '
    9. //结果切片,预分配空间为入参sql长度一半
    10. result := make([] byte, 0, sqlLength / 2)
    11. //本字符类型
    12. var charType int = NORMAL;
    13. for i := rangeBeg; i < rangeEnd; i++ {
    14. /*
    15. *utf8编码不影响判断
    16. //跳过非英文字符
    17. if sql[i] & 0x80 != 0 {
    18. //utf8编码:UTF-8是一种变长字节编码方式。对于某一个字符的UTF-8编码,如果只有一个字节则其最高二进制位为0;
    19. //如果是多字节,其第一个字节从最高位开始,连续的二进制位值为1的个数决定了其编码的位数,其余各字节均以10开头。
    20. //UTF-8最多可用到6个字节。 这里不考虑异常,因为go的字符串基本都是标准utf8编码
    21. i += getPreNotZeroCount(sql[i]) - 1
    22. continue;
    23. }
    24. */
    复制代码
    1. //本字符类型 预设为普通字符
    2. charType = NORMAL
    3. ch := sql[i]
    4. //下一个字符
    5. var chNext byte;
    6. chNext = getCharSafe(sql, rangeEnd, i + 1)
    7. //非有效sql内容结束位置
    8. endPos := 0
    9. if ch == '-' && chNext == '-' {
    10.         //单行注释
    11.         charType = LINE
    12.         //下标移到非有效字符的最后
    13.         endPos = seekToNext(sql, i + 2, rangeEnd, charType)
    14. } else if ch == '/' && chNext == '*' {
    15.         //多行注释
    16.         charType = MULTI
    17.         //下标移到非有效字符的最后
    18.         endPos = seekToNext(sql, i + 2, rangeEnd, charType)
    19. } else if ch == '\'' {
    20.         //字符串
    21.         charType = STRING
    22.         //下标移到非有效字符的最后
    23.         endPos = seekToNext(sql, i + 1, rangeEnd, charType)
    24. }
    25. //如果字符是非有效字符 则用空格代替 否则保持原样
    26. if charType == NORMAL {
    27.         result = append(result, ch)
    28. } else {
    29.         result = append(result, chPad)
    30.         i = endPos - 1
    31. }
    复制代码
    1. }
    2. return result;
    3. }
    4. /**
    复制代码
    获取字符串或者注释的右边界位置(不包含)
    1. rangeEnd是数组边界
    2. */
    3. func seekToNext(sql []byte, begPos int, rangeEnd int, charType int) int {
    4. result := begPos;
    5. switch charType {
    6. case MULTI:
    7. for ; result < rangeEnd; result++ {
    8. ch := sql[result]
    9. chNext := getCharSafe(sql, rangeEnd, result+ 1)
    复制代码
    1. if ch == '*' && chNext == '/' {
    2.                 result = result + 1;
    3.                 break;
    4.         }
    5. }
    6. break
    复制代码
    1. case LINE:
    2. for ; result < rangeEnd; result++ {
    3. ch := sql[result]
    复制代码
    1. if ch == '\n' {
    2.                 break;
    3.         }
    4. }
    5. break
    复制代码
    1. case STRING:
    2. for ; result < rangeEnd; result++ {
    3. ch := sql[result]
    4. chNext := getCharSafe(sql, rangeEnd, result + 1)
    复制代码
    1. //sql字符串里面连续的单引号被认为是' 则不是字符串结束标志
    2.         if ch == '\'' && chNext == '\'' {
    3.                 result = result + 1;
    4.                 continue;
    5.         } else if ch == '\'' {
    6.                 break;
    7.         }
    8. }
    9. break
    复制代码
    1. default:
    2. break;
    3. }
    4. result++;
    5. return result;
    6. }
    复制代码
    完整代码及单元测试已上传 https://github.com/kingstarer/kingstarer.git
    到此这篇关于使用go实现删除sql里面的注释和字符串功能的文章就介绍到这了,更多相关go删除sql注释和字符串内容请搜索咔叽论坛以前的文章或继续浏览下面的相关文章希望大家以后多多支持咔叽论坛!

    原文地址:https://www.jb51.net/article/200950.htm
    回复

    使用道具 举报

    QQ|免责声明|手机版|咔叽网单

    GMT+8, 2021-3-3 04:53

    Powered by Discuz! X3.4

    Copyright © 2001-2020, Tencent Cloud.

    快速回复 返回顶部 返回列表