2023-06-15 21:22:51 +08:00
|
|
|
|
//
|
|
|
|
|
// str_helper.go
|
|
|
|
|
// Copyright (C) 2022 tiglog <me@tiglog.com>
|
|
|
|
|
//
|
|
|
|
|
// Distributed under terms of the MIT license.
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
package helper
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"math/rand"
|
2023-07-17 23:20:05 +08:00
|
|
|
|
"strings"
|
2023-06-15 21:22:51 +08:00
|
|
|
|
"time"
|
|
|
|
|
"unicode"
|
|
|
|
|
|
2023-06-15 21:38:12 +08:00
|
|
|
|
"git.hexq.cn/tiglog/golib/crypto/gmd5"
|
2023-07-17 23:20:05 +08:00
|
|
|
|
"github.com/rs/xid"
|
2023-06-15 21:22:51 +08:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// 是否是字符串
|
|
|
|
|
func IsString(v interface{}) bool {
|
|
|
|
|
_, ok := v.(string)
|
|
|
|
|
return ok
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 随机字符串
|
|
|
|
|
func RandString(n int) string {
|
|
|
|
|
letterRunes := []rune("1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
|
|
|
|
|
rand.Seed(time.Now().UnixNano())
|
|
|
|
|
b := make([]rune, n)
|
|
|
|
|
for i := range b {
|
|
|
|
|
b[i] = letterRunes[rand.Intn(len(letterRunes))]
|
|
|
|
|
}
|
|
|
|
|
return string(b)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 首字母大写
|
|
|
|
|
func UcFirst(str string) string {
|
|
|
|
|
for _, v := range str {
|
|
|
|
|
u := string(unicode.ToUpper(v))
|
|
|
|
|
return u + str[len(u):]
|
|
|
|
|
}
|
|
|
|
|
return ""
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 首字母小写
|
|
|
|
|
func LcFirst(str string) string {
|
|
|
|
|
for _, v := range str {
|
|
|
|
|
u := string(unicode.ToLower(v))
|
|
|
|
|
return u + str[len(u):]
|
|
|
|
|
}
|
|
|
|
|
return ""
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-17 23:20:05 +08:00
|
|
|
|
// 驼峰转蛇形, XxYy => xx_yy
|
|
|
|
|
func SnakeString(str string) string {
|
|
|
|
|
data := make([]byte, 0, len(str)*2)
|
|
|
|
|
j := false
|
|
|
|
|
num := len(str)
|
|
|
|
|
for i := 0; i < num; i++ {
|
|
|
|
|
d := str[i]
|
|
|
|
|
if i > 0 && d >= 'A' && d <= 'Z' && j {
|
|
|
|
|
data = append(data, '_')
|
|
|
|
|
}
|
|
|
|
|
if d != '_' {
|
|
|
|
|
j = true
|
|
|
|
|
}
|
|
|
|
|
data = append(data, d)
|
|
|
|
|
}
|
|
|
|
|
return strings.ToLower(string(data[:]))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 蛇形转驼峰, xx_yy => XxYy
|
|
|
|
|
func CamelString(str string) string {
|
|
|
|
|
data := make([]byte, 0, len(str))
|
|
|
|
|
j := false
|
|
|
|
|
k := false
|
|
|
|
|
num := len(str) - 1
|
|
|
|
|
for i := 0; i <= num; i++ {
|
|
|
|
|
d := str[i]
|
|
|
|
|
if k == false && d >= 'A' && d <= 'Z' {
|
|
|
|
|
k = true
|
|
|
|
|
}
|
|
|
|
|
if d >= 'a' && d <= 'z' && (j || k == false) {
|
|
|
|
|
d = d - 32
|
|
|
|
|
j = false
|
|
|
|
|
k = true
|
|
|
|
|
}
|
|
|
|
|
if k && d == '_' && num > i && str[i+1] >= 'a' && str[i+1] <= 'z' {
|
|
|
|
|
j = true
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
data = append(data, d)
|
|
|
|
|
}
|
|
|
|
|
return string(data[:])
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-15 21:22:51 +08:00
|
|
|
|
// 乱序字符串
|
|
|
|
|
func Shuffle(str string) string {
|
|
|
|
|
if str == "" {
|
|
|
|
|
return str
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
runes := []rune(str)
|
|
|
|
|
index := 0
|
|
|
|
|
|
|
|
|
|
for i := len(runes) - 1; i > 0; i-- {
|
|
|
|
|
index = rand.Intn(i + 1)
|
|
|
|
|
|
|
|
|
|
if i != index {
|
|
|
|
|
runes[i], runes[index] = runes[index], runes[i]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return string(runes)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 反序字符串
|
|
|
|
|
func Reverse(str string) string {
|
|
|
|
|
n := len(str)
|
|
|
|
|
runes := make([]rune, n)
|
|
|
|
|
for _, r := range str {
|
|
|
|
|
n--
|
|
|
|
|
runes[n] = r
|
|
|
|
|
}
|
|
|
|
|
return string(runes[n:])
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 唯一字符串
|
|
|
|
|
// 返回字符串长度为 20
|
|
|
|
|
func GenId() string {
|
|
|
|
|
guid := xid.New()
|
|
|
|
|
return guid.String()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 可变长度的唯一字符串
|
|
|
|
|
// 长度太短,可能就不唯一了
|
|
|
|
|
// 长度大于等于 16 为最佳
|
|
|
|
|
// 长度小于20时,为 GenId 的值 md5 后的前缀,因此,理论上前6位也能在大多数情况
|
|
|
|
|
// 下唯一
|
|
|
|
|
func Uniq(l int) string {
|
|
|
|
|
if l <= 0 {
|
|
|
|
|
panic("wrong length param")
|
|
|
|
|
}
|
|
|
|
|
ret := GenId()
|
|
|
|
|
hl := len(ret)
|
|
|
|
|
if l < hl {
|
|
|
|
|
t, err := gmd5.EncryptString(ret)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return ret[hl-l:]
|
|
|
|
|
}
|
|
|
|
|
return t[:l]
|
|
|
|
|
}
|
|
|
|
|
mhac_len := 6
|
|
|
|
|
pl := len(ret)
|
|
|
|
|
var hash string
|
|
|
|
|
for l > pl {
|
|
|
|
|
hash = GenId()
|
|
|
|
|
hash = hash[mhac_len:]
|
|
|
|
|
ret += hash
|
|
|
|
|
pl += len(hash)
|
|
|
|
|
}
|
|
|
|
|
// log.Println("ret=", ret, ", pl=", pl, ", l=", l)
|
|
|
|
|
return ret[0:l]
|
|
|
|
|
}
|
2023-09-20 16:49:31 +08:00
|
|
|
|
|
|
|
|
|
func GetCjkRange(code int) string {
|
|
|
|
|
var result string
|
2023-09-21 20:56:57 +08:00
|
|
|
|
if code >= 0x4E00 && code <= 0x9FFF {
|
|
|
|
|
result = "CJK"
|
|
|
|
|
} else if code >= 0x3400 && code <= 0x4DBF {
|
2023-09-20 16:49:31 +08:00
|
|
|
|
result = "EXT-A"
|
|
|
|
|
} else if code >= 0x20000 && code <= 0x2A6DF {
|
|
|
|
|
result = "EXT-B"
|
|
|
|
|
} else if code >= 0x2A700 && code <= 0x2B739 {
|
|
|
|
|
result = "EXT-C"
|
|
|
|
|
} else if code >= 0x2B740 && code <= 0x2B81D {
|
|
|
|
|
result = "EXT-D"
|
|
|
|
|
} else if code >= 0x2B820 && code <= 0x2CEA1 {
|
|
|
|
|
result = "EXT-E"
|
|
|
|
|
} else if code >= 0x2CEB0 && code <= 0x2EBE0 {
|
|
|
|
|
result = "EXT-F"
|
|
|
|
|
} else if code >= 0x30000 && code <= 0x3134A {
|
|
|
|
|
result = "EXT-G"
|
|
|
|
|
} else if code >= 0x31350 && code <= 0x323AF {
|
|
|
|
|
result = "EXT-H"
|
2023-09-21 20:56:57 +08:00
|
|
|
|
} else if code >= 0x2EBF0 && code <= 0x2EE5D {
|
|
|
|
|
result = "EXT-I"
|
|
|
|
|
} else if code == 0x3007 {
|
|
|
|
|
result = "零"
|
2023-09-24 18:52:55 +08:00
|
|
|
|
} else if code >= 0x31C0 && code <= 0x31EF {
|
2023-09-21 20:56:57 +08:00
|
|
|
|
result = "笔画"
|
2023-09-25 18:08:43 +08:00
|
|
|
|
} else if code >= 0x2E80 && code <= 0x2EFF {
|
|
|
|
|
result = "部首补充"
|
2023-09-20 16:49:31 +08:00
|
|
|
|
} else if code >= 0xE000 && code <= 0xF8FF {
|
|
|
|
|
result = "PUA"
|
2023-09-21 20:56:57 +08:00
|
|
|
|
} else if code >= 0x2F00 && code <= 0x2FDF {
|
|
|
|
|
result = "康熙部首"
|
|
|
|
|
} else if code >= 0xF900 && code <= 0xFAD9 {
|
|
|
|
|
result = "兼容区"
|
2023-09-25 18:08:43 +08:00
|
|
|
|
} else if code >= 0xFE30 && code <= 0xFE4F {
|
|
|
|
|
result = "兼容形式"
|
2023-09-21 20:56:57 +08:00
|
|
|
|
} else if code >= 0x2F800 && code <= 0x2FA1D {
|
2023-09-25 18:08:43 +08:00
|
|
|
|
result = "兼容表意文字增补"
|
|
|
|
|
} else if code >= 0x3100 && code <= 0x312F {
|
|
|
|
|
result = "注音"
|
2023-09-21 20:56:57 +08:00
|
|
|
|
} else if code >= 0x17000 && code <= 0x187F7 {
|
|
|
|
|
result = "西夏文"
|
2023-09-24 20:01:41 +08:00
|
|
|
|
} else if code >= 0x18800 && code <= 0x18AFF {
|
2023-09-25 18:08:43 +08:00
|
|
|
|
result = "西夏文部首"
|
2023-09-24 20:01:41 +08:00
|
|
|
|
} else if code >= 0x18D00 && code <= 0x18D08 {
|
2023-09-25 18:08:43 +08:00
|
|
|
|
result = "西夏文增补"
|
2023-09-24 20:01:41 +08:00
|
|
|
|
} else if code >= 0x18B00 && code <= 0x18CFF {
|
|
|
|
|
result = "契丹文"
|
2023-09-25 18:08:43 +08:00
|
|
|
|
} else if code >= 0x0900 && code <= 0x097F {
|
|
|
|
|
result = "梵文"
|
|
|
|
|
} else if code >= 0x1B170 && code <= 0x1B2FF {
|
|
|
|
|
result = "女书"
|
|
|
|
|
} else if code >= 0x0F00 && code <= 0x0FFF {
|
|
|
|
|
result = "藏文"
|
|
|
|
|
} else if code >= 0x1800 && code <= 0x18AF {
|
|
|
|
|
result = "蒙古语"
|
|
|
|
|
} else if code >= 0x30A0 && code <= 0x30FF {
|
|
|
|
|
result = "日文片假名"
|
|
|
|
|
} else if code >= 0x31F0 && code <= 0x31FF {
|
|
|
|
|
result = "片假名扩展"
|
|
|
|
|
} else if code >= 0x3040 && code <= 0x309F {
|
|
|
|
|
result = "日文平假名"
|
|
|
|
|
} else if code >= 0x3000 && code <= 0x303F {
|
|
|
|
|
result = "符号和标点符号"
|
|
|
|
|
} else if code >= 0x2E00 && code <= 0x2E7F {
|
|
|
|
|
result = "补充标点符号"
|
|
|
|
|
} else if code >= 0x2200 && code <= 0x22FF {
|
|
|
|
|
result = "数学运算符号"
|
|
|
|
|
} else if code >= 0x2A00 && code <= 0x2AFF {
|
|
|
|
|
result = "补充数学运算符"
|
|
|
|
|
} else if code >= 0x2150 && code <= 0x218F {
|
|
|
|
|
result = "数字形式符号"
|
|
|
|
|
} else if code >= 0x2300 && code <= 0x23FF {
|
|
|
|
|
result = "杂项技术符号"
|
|
|
|
|
} else if code >= 0x27C0 && code <= 0x27EF {
|
|
|
|
|
result = "杂项数学符号-A"
|
|
|
|
|
} else if code >= 0x2980 && code <= 0x29FF {
|
|
|
|
|
result = "杂项数学符号-B"
|
|
|
|
|
} else if code >= 0x2190 && code <= 0x21FF {
|
|
|
|
|
result = "箭头符号"
|
|
|
|
|
} else if code >= 0x3190 && code <= 0x319F {
|
|
|
|
|
result = "汉文训读"
|
|
|
|
|
} else if code >= 0x3200 && code <= 0x32FF {
|
|
|
|
|
result = "中日韩带圈字符及月份"
|
|
|
|
|
} else if code >= 0x1F100 && code <= 0x1F1FF {
|
|
|
|
|
result = "带圈字母数字补充"
|
|
|
|
|
} else if code >= 0x1F200 && code <= 0x1F2FF {
|
|
|
|
|
result = "带圈表意文字补充"
|
|
|
|
|
} else if code >= 0x1D100 && code <= 0x1D1FF {
|
|
|
|
|
result = "音乐符号"
|
|
|
|
|
} else if code >= 0x1D360 && code <= 0x1D37F {
|
|
|
|
|
result = "算筹"
|
|
|
|
|
} else if code >= 0x1D300 && code <= 0x1D35F {
|
|
|
|
|
result = "太玄经符号"
|
|
|
|
|
} else if code >= 0x1F600 && code <= 0x1F64F {
|
|
|
|
|
result = "表情符号"
|
|
|
|
|
} else if code >= 0x2070 && code <= 0x209F {
|
|
|
|
|
result = "上下标"
|
|
|
|
|
} else if code >= 0x1D400 && code <= 0x1D7FF {
|
|
|
|
|
result = "字母和数字符号"
|
|
|
|
|
} else if code >= 0x25A0 && code <= 0x25FF {
|
|
|
|
|
result = "几何形状"
|
|
|
|
|
} else if code >= 0x1F780 && code <= 0x1F7FF {
|
|
|
|
|
result = "几何图形扩展"
|
2023-09-25 15:18:24 +08:00
|
|
|
|
} else if code >= 0x2630 && code <= 0x2637 {
|
|
|
|
|
result = "八卦"
|
|
|
|
|
} else if code >= 0x19904 && code <= 0x19967 {
|
2023-09-25 18:08:43 +08:00
|
|
|
|
result = "易经六十四卦符号"
|
|
|
|
|
} else if code >= 0x1FA00 && code <= 0x1FA6F {
|
|
|
|
|
result = "象棋符号"
|
|
|
|
|
} else if code >= 0x0370 && code <= 0x03FF {
|
|
|
|
|
result = "希腊语和科普特语"
|
|
|
|
|
} else if code >= 0x1F000 && code <= 0x1F02F {
|
|
|
|
|
result = "麻将牌"
|
|
|
|
|
} else if code >= 0x1F0A0 && code <= 0x1F0FF {
|
|
|
|
|
result = "扑克牌"
|
|
|
|
|
} else if code >= 0x20A0 && code <= 0x20CF {
|
|
|
|
|
result = "货币符号"
|
|
|
|
|
} else if code >= 0x1F680 && code <= 0x1F6FF {
|
|
|
|
|
result = "交通和地图符号"
|
|
|
|
|
} else if code >= 0x1F030 && code <= 0x1F09F {
|
|
|
|
|
result = "多米诺骨牌"
|
|
|
|
|
} else if code >= 0x1F300 && code <= 0x1F5FF {
|
|
|
|
|
result = "杂项符号和象形文字"
|
|
|
|
|
} else if code >= 0x2500 && code <= 0x257F {
|
|
|
|
|
result = "方框绘制字符"
|
|
|
|
|
} else if code >= 0x1F700 && code <= 0x1F77F {
|
|
|
|
|
result = "炼金术符号"
|
2023-09-20 16:49:31 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 获取某个字的 unicode 值
|
|
|
|
|
func Ord(in string) int {
|
|
|
|
|
s := []rune(in)
|
|
|
|
|
return int(s[0])
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 把 unicode 值转成字符串
|
|
|
|
|
func Chr(code int) string {
|
|
|
|
|
return string(rune(code))
|
|
|
|
|
}
|