regexp.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. // Copyright 2019 github.com. All rights reserved.
  2. // Use of this source code is governed by github.com.
  3. package util
  4. import (
  5. "regexp"
  6. )
  7. const (
  8. // 匹配大陆电话
  9. cnPhonePattern = `((\d{3,4})-?)?` + // 区号
  10. `\d{5,10}` + // 号码,95500等5位数的,7位,8位,以及400开头的10位数
  11. `(-\d{1,4})?` // 分机号,分机号的连接符号不能省略。
  12. // 匹配大陆手机号码
  13. cnMobilePattern = `(0|\+?86)?` + // 匹配 0,86,+86
  14. `(13[0-9]|` + // 130-139
  15. `14[579]|` + // 145,147,149
  16. `15[0-9]|` + // 150-159
  17. `17[0-9]|` + // 170-179
  18. `18[0-9]|` + // 180-189
  19. `16[56]|` + // 165,1666
  20. `19[0126789])` + // 191,198,199
  21. `[0-9]{8}`
  22. // 匹配大陆手机号或是电话号码
  23. cnTelPattern = "(" + cnPhonePattern + ")|(" + cnMobilePattern + ")"
  24. // 匹配邮箱
  25. emailPattern = `^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$`
  26. // 匹配 IP4
  27. ip4Pattern = `((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)`
  28. // 匹配 IP6,参考以下网页内容:
  29. // http://blog.csdn.net/jiangfeng08/article/details/7642018
  30. ip6Pattern = `(([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|` +
  31. `(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|` +
  32. `(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|` +
  33. `(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|` +
  34. `(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|` +
  35. `(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|` +
  36. `(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|` +
  37. `(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))`
  38. // 同时匹配 IP4 和 IP6
  39. ipPattern = "(" + ip4Pattern + ")|(" + ip6Pattern + ")"
  40. // 匹配域名
  41. domainPattern = `[a-zA-Z0-9][a-zA-Z0-9_-]{0,62}(\.[a-zA-Z0-9][a-zA-Z0-9_-]{0,62})*(\.[a-zA-Z][a-zA-Z0-9]{0,10}){1}`
  42. // 匹配 URL
  43. urlPattern = `((https|http|ftp|rtsp|mms)?://)?` + // 协议
  44. `(([0-9a-zA-Z]+:)?[0-9a-zA-Z_-]+@)?` + // pwd:user@
  45. "(" + ipPattern + "|(" + domainPattern + "))" + // IP 或域名
  46. `(:\d{1,5})?` + // 端口
  47. `(/+[a-zA-Z0-9][a-zA-Z0-9_.-]*)*/*` + // path
  48. `(\?([a-zA-Z0-9_-]+(=.*&?)*)*)*` // query
  49. idCertPattern = `^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$`
  50. )
  51. var (
  52. email = regexpCompile(emailPattern)
  53. ip4 = regexpCompile(ip4Pattern)
  54. ip6 = regexpCompile(ip6Pattern)
  55. ip = regexpCompile(ipPattern)
  56. url = regexpCompile(urlPattern)
  57. cnPhone = regexpCompile(cnPhonePattern)
  58. cnMobile = regexpCompile(cnMobilePattern)
  59. cnTel = regexpCompile(cnTelPattern)
  60. cnIdCert = regexpCompile(idCertPattern)
  61. )
  62. func regexpCompile(str string) *regexp.Regexp {
  63. return regexp.MustCompile("^" + str + "$")
  64. }
  65. // 判断val是否能正确匹配exp中的正则表达式。
  66. // val可以是[]byte, []rune, string类型。
  67. func isMatch(exp *regexp.Regexp, val interface{}) bool {
  68. switch v := val.(type) {
  69. case []rune:
  70. return exp.MatchString(string(v))
  71. case []byte:
  72. return exp.Match(v)
  73. case string:
  74. return exp.MatchString(v)
  75. default:
  76. return false
  77. }
  78. }
  79. // IsCNPhone 验证中国大陆的电话号码。支持如下格式:
  80. // 0578-12345678-1234
  81. // 057812345678-1234
  82. // 若存在分机号,则分机号的连接符不能省略。
  83. func IsCNPhone(val interface{}) bool {
  84. return isMatch(cnPhone, val)
  85. }
  86. // IsCNMobile 验证中国大陆的手机号码
  87. func IsCNMobile(val interface{}) bool {
  88. return isMatch(cnMobile, val)
  89. }
  90. // IsCNTel 验证手机和电话类型
  91. func IsCNTel(val interface{}) bool {
  92. return isMatch(cnTel, val)
  93. }
  94. // IsURL 验证一个值是否标准的URL格式。支持IP和域名等格式
  95. func IsURL(val interface{}) bool {
  96. return isMatch(url, val)
  97. }
  98. // IsIP 验证一个值是否为IP,可验证IP4和IP6
  99. func IsIP(val interface{}) bool {
  100. return isMatch(ip, val)
  101. }
  102. // IsIP6 验证一个值是否为IP6
  103. func IsIP6(val interface{}) bool {
  104. return isMatch(ip6, val)
  105. }
  106. // IsIP4 验证一个值是滞为IP4
  107. func IsIP4(val interface{}) bool {
  108. return isMatch(ip4, val)
  109. }
  110. // IsEmail 验证一个值是否匹配一个邮箱。
  111. func IsEmail(val interface{}) bool {
  112. return isMatch(email, val)
  113. }
  114. // IsIdCert 验证一个值是否匹配身份证号码。
  115. func IsIdCert(val interface{}) bool {
  116. return isMatch(cnIdCert, val)
  117. }