2.go语言strings库基本使用

内容主要来源:go标准库之strings — 字符串操作

strings库

主要用于操作字符串

string 类型可以看成是一种特殊的 slice 类型,因此获取长度可以用内置的函数 len;同时支持 切片 操作

字符串比较

// Compare 函数,用于比较两个字符串的大小,如果两个字符串相等,返回为 0。如果 a 小于 b ,返回 -1 ,反之返回 1 。不推荐使用这个函数,直接使用 == != > < >= <= 等一系列运算符更加直观。
func Compare(a, b string) int 
// EqualFold 函数,计算 s 与 t 忽略字母大小写后是否相等。
func EqualFold(s, t string) bool
package main

import (
	"fmt"
	"strings"
)

func main() {

	var str1 string = "hello"
	var str2 string = "world"

	// 比较字符串
	fmt.Println(strings.Compare(str1, str2)) // -1
	fmt.Println(strings.Compare(str1, str1)) // 0
	fmt.Println(strings.Compare(str2, str1)) // 1

	fmt.Println(strings.EqualFold("HELLO", "hello")) // true
	fmt.Println(strings.EqualFold("HEllo", "hello")) // true
	fmt.Println(strings.EqualFold("HEllo", "world")) // false

}

是否存在某个字符或子串

主要有3个函数

// 子串 substr 在 s 中,返回 true
func Contains(s, substr string) bool
// chars 中任何一个 Unicode 代码点在 s 中,返回 true
func ContainsAny(s, chars string) bool
// Unicode 代码点 r 在 s 中,返回 true
func ContainsRune(s string, r rune) bool
package main

import (
	"fmt"
	"strings"
)

func main() {

	str1 := "hello,zhangsan"

	fmt.Println(strings.Contains(str1, "hello"))    // true
	fmt.Println(strings.Contains(str1, "hezhang"))  // false
	fmt.Println(strings.Contains(str1, "he zhang")) // false
	fmt.Println("-------------------------------------")

	fmt.Println(strings.ContainsAny(str1, "h"))   // true
	fmt.Println(strings.ContainsAny(str1, "b"))   // false
	fmt.Println(strings.ContainsAny(str1, "h b")) // true
	fmt.Println(strings.ContainsAny(str1, ", b")) // true
	fmt.Println(strings.ContainsAny(str1, "hb"))  // true
	fmt.Println("-------------------------------------")

	fmt.Println(strings.ContainsRune(str1, 'h')) // true

}
  • strings.ContainsAny()中第二个参数 chars 中任意一个字符(Unicode Code Point)如果在第一个参数 s 中存在,则返回 true

  • strings.ContainsRune() 函数只能用于检查字符串是否包含单个字符,不能用于检查字符串中是否包含多个字符,第二个参数为 rune 类型,需要用单引号 '' 来定义

子串出现次数

func Count(s, sep string) int

在 Count 的实现中,处理了几种特殊情况,属于字符匹配预处理的一部分。这里要特别说明一下的是当 sep 为空时,Count 的返回值是:utf8.RuneCountInString(s) + 1

Count 是计算子串在字符串中出现的无重叠的次数

package main

import (
	"fmt"
	"strings"
)

func main() {

	fmt.Println(strings.Count("cheese", "e")) // 3
	fmt.Println(len("你好张三"))                  // 12
	fmt.Println(strings.Count("你好张三", ""))    // 5
	fmt.Println(strings.Count("fivevevev", "vev")) // 2
    
}

字符串分割为[]string

该包提供了六个三组分割函数:Fields 和 FieldsFunc、Split 和 SplitAfter、SplitN 和 SplitAfterN。

Fields 和 FieldsFunc

func Fields(s string) []string
func FieldsFunc(s string, f func(rune) bool) []string

Fields 用一个或多个连续的空格分隔字符串 s,返回子字符串的数组(slice)。如果字符串 s 只包含空格,则返回空列表 ([]string 的长度为 0)。其中,空格的定义是 unicode.IsSpace

常见间隔符包括:’\t’, ‘\n’, ‘\v’, ‘\f’, ‘\r’, ‘ ‘, U+0085 (NEL), U+00A0 (NBSP)

由于是用空格分隔,因此结果中不会含有空格或空子字符串

FieldsFunc 用这样的 Unicode 代码点 c 进行分隔:满足 f© 返回 true。该函数返回[]string。如果字符串 s 中所有的代码点 (unicode code points) 都满足 f© 或者 s 是空,则 FieldsFunc 返回空 slice。

package main

import (
	"fmt"
	"strings"
)

func main() {

	s := strings.Fields("   hello    world    zhangsan")
	fmt.Println(len(s)) // 3
	fmt.Println(s)      // [hello world zhangsan]

	// 以字符c进行分割
	s = strings.FieldsFunc("abcabcabcab", func(r rune) bool {
		return r == 'c'
	})
	fmt.Println(s) // [ab ab ab ab]

}

Split 和 SplitAfter、 SplitN 和 SplitAfterN

func Split(s, sep string) []string { return genSplit(s, sep, 0, -1) }
func SplitAfter(s, sep string) []string { return genSplit(s, sep, len(sep), -1) }
func SplitN(s, sep string, n int) []string { return genSplit(s, sep, 0, n) }
func SplitAfterN(s, sep string, n int) []string { return genSplit(s, sep, len(sep), n) }

这四个函数都是通过 sep 进行分割,返回[]string。如果 sep 为空,相当于分成一个个的 UTF-8 字符,如 Split("abc",""),得到的是[a b c]。

Split(s, sep) 和 SplitN(s, sep, -1) 等价;SplitAfter(s, sep) 和 SplitAfterN(s, sep, -1) 等价。

Split 和 SplitAfter 的区别是后者会保留要分割的 sep 字符

package main

import (
	"fmt"
	"strings"
)

func main() {

	fmt.Println(strings.Split("hello,world,zhang", ","))	 // [hello world zhang]
	fmt.Println(strings.SplitAfter("hello,world,zhang", ","))// [hello, world, zhang]

}

带 N 的方法可以通过最后一个参数 n 控制返回的结果中的 slice 中的元素个数,当 n < 0 时,返回所有的子字符串;当 n == 0 时,返回的结果是 nil;当 n > 0 时,表示返回的 slice 中最多只有 n 个元素,其中,最后一个元素不会分割,比如:

package main

import (
	"fmt"
	"strings"
)

func main() {
    
	fmt.Println(strings.SplitN("hello,world,zhang", ",", -1)) // [hello world zhang]
	fmt.Println(strings.SplitN("hello,world,zhang", ",", 0))  // []
	fmt.Println(strings.SplitN("hello,world,zhang", ",", 1))  // [hello,world,zhang]
	fmt.Println(strings.SplitN("hello,world,zhang", ",", 2))  // [hello world,zhang]
	fmt.Println(strings.SplitN("hello,world,zhang", ",", 3))  // [hello world zhang]

}

官方例子,注意结果

fmt.Printf("%q\n", strings.Split("a,b,c", ","))
fmt.Printf("%q\n", strings.Split("a man a plan a canal panama", "a "))
fmt.Printf("%q\n", strings.Split(" xyz ", ""))
fmt.Printf("%q\n", strings.Split("", "Bernardo O'Higgins"))

结果:

["a" "b" "c"]
["" "man " "plan " "canal panama"]
[" " "x" "y" "z" " "]
[""]

字符串是否有某个前缀或后缀

// s 中是否以 prefix 开始
func HasPrefix(s, prefix string) bool {
  return len(s) >= len(prefix) && s[0:len(prefix)] == prefix
}
// s 中是否以 suffix 结尾
func HasSuffix(s, suffix string) bool {
  return len(s) >= len(suffix) && s[len(s)-len(suffix):] == suffix
}

如果 prefix 或 suffix 为 “” , 返回值总是 true。

示例:

fmt.Println(strings.HasPrefix("Gopher", "Go"))
fmt.Println(strings.HasPrefix("Gopher", "C"))
fmt.Println(strings.HasPrefix("Gopher", ""))
fmt.Println(strings.HasSuffix("Amigo", "go"))
fmt.Println(strings.HasSuffix("Amigo", "Ami"))
fmt.Println(strings.HasSuffix("Amigo", ""))

输出结果:

true
false
true
true
false
true

字符或子串在字符串中出现的位置

// 在 s 中查找 sep 的第一次出现,返回第一次出现的索引
func Index(s, sep string) int
// 在 s 中查找字节 c 的第一次出现,返回第一次出现的索引
func IndexByte(s string, c byte) int
// chars 中任何一个 Unicode 代码点在 s 中首次出现的位置
func IndexAny(s, chars string) int
// 查找字符 c 在 s 中第一次出现的位置,其中 c 满足 f(c) 返回 true
func IndexFunc(s string, f func(rune) bool) int
// Unicode 代码点 r 在 s 中第一次出现的位置
func IndexRune(s string, r rune) int

// 有三个对应的查找最后一次出现的位置
func LastIndex(s, sep string) int
func LastIndexByte(s string, c byte) int
func LastIndexAny(s, chars string) int
func LastIndexFunc(s string, f func(rune) bool) int

Contain 相关的函数内部调用的是响应的 Index 函数

package main

import (
	"fmt"
	"strings"
	"unicode"
)

func main() {

	s := "hello,world,zhang"

	fmt.Println(strings.Index(s, "o"))          // 4
	fmt.Println(strings.Index(s, "ll"))         // 2
	fmt.Println(strings.IndexAny(s, "l w"))     // 2
	fmt.Println(strings.IndexAny(s, "b w"))     // 6
	fmt.Println(strings.LastIndex(s, "o"))      // 7
	fmt.Println(strings.LastIndexAny(s, "b n")) // 15

    // 看字符串中是否有汉字
	han := func(c rune) bool {
		return unicode.Is(unicode.Han, c) // 汉字
	}
	fmt.Println(strings.IndexFunc("Hello, world", han))
	fmt.Println(strings.IndexFunc("Hello, 世界", han))
    
}

字符串 JOIN 操作

将字符串数组(或 slice)连接起来可以通过 Join 实现

func Join(a []string, sep string) string
package main

import (
	"fmt"
	"strings"
)

func main() {

	s := []string{"hello", "world", "zhang"}
	fmt.Println(strings.Join(s, ",")) // hello,world,zhang
	fmt.Println(strings.Join(s, " ")) // hello world zhang

}

字符串重复几次

func Repeat(s string, count int) string

将 s 重复 count 次,如果 count 为负数或返回值长度 len(s)*count 超出 string 上限会导致 panic

package main

import (
	"fmt"
	"strings"
)

func main() {

	fmt.Println("ba" + strings.Repeat("na", 2))

}

字符串子串替换

进行字符串替换时,考虑到性能问题,能不用正则尽量别用,应该用这里的函数。

// 用 new 替换 s 中的 old,一共替换 n 个。
// 如果 n < 0,则不限制替换次数,即全部替换
func Replace(s, old, new string, n int) string
// 该函数内部直接调用了函数 Replace(s, old, new , -1)
func ReplaceAll(s, old, new string) string

使用示例:

fmt.Println(strings.Replace("oink oink oink", "k", "ky", 2))
fmt.Println(strings.Replace("oink oink oink", "oink", "moo", -1))
fmt.Println(strings.ReplaceAll("oink oink oink", "oink", "moo"))

输出:

oinky oinky oink
moo moo moo
moo moo moo

如果我们希望一次替换多个,比如我们希望替换 This is <b>HTML</b> 中的 <><>,可以调用上面的函数两次。但标准库提供了另外的方法进行这种替换。

大小写转换

func ToLower(s string) string
func ToLowerSpecial(c unicode.SpecialCase, s string) string
func ToUpper(s string) string
func ToUpperSpecial(c unicode.SpecialCase, s string) string

大小写转换包含了 4 个相关函数,ToLower,ToUpper 用于大小写转换。ToLowerSpecial,ToUpperSpecial 可以转换特殊字符的大小写。
举个例子:

fmt.Println(strings.ToLower("HELLO WORLD"))
fmt.Println(strings.ToLower("Ā Á Ǎ À"))
fmt.Println(strings.ToLowerSpecial(unicode.TurkishCase, "壹"))
fmt.Println(strings.ToLowerSpecial(unicode.TurkishCase, "HELLO WORLD"))
fmt.Println(strings.ToLower("Önnek İş"))
fmt.Println(strings.ToLowerSpecial(unicode.TurkishCase, "Önnek İş"))

fmt.Println(strings.ToUpper("hello world"))
fmt.Println(strings.ToUpper("ā á ǎ à"))
fmt.Println(strings.ToUpperSpecial(unicode.TurkishCase, "一"))
fmt.Println(strings.ToUpperSpecial(unicode.TurkishCase, "hello world"))
fmt.Println(strings.ToUpper("örnek iş"))
fmt.Println(strings.ToUpperSpecial(unicode.TurkishCase, "örnek iş"))

输出结果:

hello world
ā á ǎ à
壹
hello world
önnek iş
önnek iş
HELLO WORLD
Ā Á Ǎ À       // 汉字拼音有效
一           //  汉字无效
HELLO WORLD
ÖRNEK IŞ
ÖRNEK İŞ    // 有细微差别

修剪

// 将 s 左侧和右侧中匹配 cutset 中的任一字符的字符去掉
func Trim(s string, cutset string) string
// 将 s 左侧的匹配 cutset 中的任一字符的字符去掉
func TrimLeft(s string, cutset string) string
// 将 s 右侧的匹配 cutset 中的任一字符的字符去掉
func TrimRight(s string, cutset string) string
// 如果 s 的前缀为 prefix 则返回去掉前缀后的 string , 否则 s 没有变化。
func TrimPrefix(s, prefix string) string
// 如果 s 的后缀为 suffix 则返回去掉后缀后的 string , 否则 s 没有变化。
func TrimSuffix(s, suffix string) string
// 将 s 左侧和右侧的间隔符去掉。常见间隔符包括:'\t', '\n', '\v', '\f', '\r', ' ', U+0085 (NEL)
func TrimSpace(s string) string
// 将 s 左侧和右侧的匹配 f 的字符去掉
func TrimFunc(s string, f func(rune) bool) string
// 将 s 左侧的匹配 f 的字符去掉
func TrimLeftFunc(s string, f func(rune) bool) string
// 将 s 右侧的匹配 f 的字符去掉
func TrimRightFunc(s string, f func(rune) bool) string

包含了 9 个相关函数用于修剪字符串。

举个例子:

x := "!!!@@@你好,!@#$ Gophers###$$$"
fmt.Println(strings.Trim(x, "@#$!%^&*()_+=-"))
fmt.Println(strings.TrimLeft(x, "@#$!%^&*()_+=-"))
fmt.Println(strings.TrimRight(x, "@#$!%^&*()_+=-"))
fmt.Println(strings.TrimSpace(" \t\n Hello, Gophers \n\t\r\n"))
fmt.Println(strings.TrimPrefix(x, "!"))
fmt.Println(strings.TrimSuffix(x, "$"))

f := func(r rune) bool {
    return !unicode.Is(unicode.Han, r) // 非汉字返回 true
}
fmt.Println(strings.TrimFunc(x, f))
fmt.Println(strings.TrimLeftFunc(x, f))
fmt.Println(strings.TrimRightFunc(x, f))

输出结果:

你好,!@#$ Gophers
你好,!@#$ Gophers###$$$
!!!@@@你好,!@#$ Gophers
Hello, Gophers
!!@@@你好,!@#$ Gophers###$$$
!!!@@@你好,!@#$ Gophers###$$
你好
你好,!@#$ Gophers###$$$
!!!@@@你好
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一弓虽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值