Golang(四)正则表达式使用

0. 前言

1. 正则表达式

1.1 单一字符

1. 匹配任意一个字符,如果设置 s = true,则可以匹配换行符 2 3 [字符类] 匹配“字符类”中的一个字符,“字符类”见后面的说明 4 [^字符类] 匹配“字符类”外的一个字符,“字符类”见后面的说明 5 6 \小写Perl标记 匹配“Perl类”中的一个字符,“Perl类”见后面的说明 7 \大写Perl标记 匹配“Perl类”外的一个字符,“Perl类”见后面的说明 8 9 [:ASCII类名:] 匹配“ASCII类”中的一个字符,“ASCII类”见后面的说明 10 [:^ASCII类名:] 匹配“ASCII类”外的一个字符,“ASCII类”见后面的说明 11 12 \pUnicode普通类名 匹配“Unicode类”中的一个字符(仅普通类),“Unicode类”见后面的说明 13 \PUnicode普通类名 匹配“Unicode类”外的一个字符(仅普通类),“Unicode类”见后面的说明 14 15 \p{Unicode类名} 匹配“Unicode类”中的一个字符,“Unicode类”见后面的说明 16 \P{Unicode类名} 匹配“Unicode类”外的一个字符,“Unicode类”见后面的说明

1.2 复合

1 xy 匹配 xy(x 后面跟随 y) 2 x|y 匹配 x 或 y (优先匹配 x)

1.3 重复

1x* 匹配零个或多个 x,优先匹配更多(贪婪) 2 x+ 匹配一个或多个 x,优先匹配更多(贪婪) 3 x? 匹配零个或一个 x,优先匹配一个(贪婪) 4 x{n,m} 匹配 n 到 m 个 x,优先匹配更多(贪婪) 5 x{n,} 匹配 n 个或多个 x,优先匹配更多(贪婪) 6 x{n} 只匹配 n 个 x 7 x*? 匹配零个或多个 x,优先匹配更少(非贪婪) 8 x+? 匹配一个或多个 x,优先匹配更少(非贪婪) 9 x?? 匹配零个或一个 x,优先匹配零个(非贪婪) 10 x{n,m}? 匹配 n 到 m 个 x,优先匹配更少(非贪婪) 11 x{n,}? 匹配 n 个或多个 x,优先匹配更少(非贪婪) 12 x{n}? 只匹配 n 个 x

1.4 分组

1 (子表达式) 被捕获的组,该组被编号 (子匹配) 2 (?P<命名>子表达式) 被捕获的组,该组被编号且被命名 (子匹配) 3 (?:子表达式) 非捕获的组 (子匹配) 4 (?标记) 在组内设置标记,非捕获,标记影响当前组后的正则表达式 5 (?标记:子表达式) 在组内设置标记,非捕获,标记影响当前组内的子表达式 6 7 标记的语法是: 8 xyz (设置 xyz 标记) 9 -xyz (清除 xyz 标记) 10 xy-z (设置 xy 标记, 清除 z 标记) 11 12 可以设置的标记有: 13 i 不区分大小写 (默认为 false) 14 m 多行模式:让 ^ 和 $ 匹配整个文本的开头和结尾,而非行首和行尾(默认为 false) 15 s 让 . 匹配 \n (默认为 false) 16 U 非贪婪模式:交换 x* 和 x*? 等的含义 (默认为 false)

1.5 位置标记 

1^ 如果标记 m=true 则匹配行首,否则匹配整个文本的开头(m 默认为 false2 $ 如果标记 m=true 则匹配行尾,否则匹配整个文本的结尾(m 默认为 false3 \A 匹配整个文本的开头,忽略 m 标记 4 \b 匹配单词边界 5 \B 匹配非单词边界 6 \z 匹配整个文本的结尾,忽略 m 标记

1.6 转义序列 

1 \a 匹配响铃符 (相当于 \x07) 2 注意:正则表达式中不能使用 \b 匹配退格符,因为 \b 被用来匹配单词边界, 3 可以使用 \x08 表示退格符。 4 \f 匹配换页符 (相当于 \x0C) 5 \t 匹配横向制表符(相当于 \x09) 6 \n 匹配换行符 (相当于 \x0A) 7 \r 匹配回车符 (相当于 \x0D) 8 \v 匹配纵向制表符(相当于 \x0B) 9 \123 匹配 8 進制编码所代表的字符(必须是 3 位数字) 10 \x7F 匹配 16 進制编码所代表的字符(必须是 3 位数字) 11 \x{10FFFF} 匹配 16 進制编码所代表的字符(最大值 10FFFF ) 12 \Q...\E 匹配 \Q 和 \E 之间的文本,忽略文本中的正则语法 13 14 \\ 匹配字符 \ 15 \^ 匹配字符 ^ 16 \$ 匹配字符 $ 17 \. 匹配字符 . 18 \* 匹配字符 * 19 \+ 匹配字符 + 20 \? 匹配字符 ? 21 \{ 匹配字符 { 22 \} 匹配字符 } 23 \( 匹配字符 ( 24 \) 匹配字符 ) 25 \[ 匹配字符 [ 26 \] 匹配字符 ] 27 \| 匹配字符 |

1.7 将“命名字符类”作为“字符类”的元素

1 [\d] 匹配数字 (相当于 \d) 2 [^\d] 匹配非数字 (相当于 \D) 3 [\D] 匹配非数字 (相当于 \D) 4 [^\D] 匹配数字 (相当于 \d) 5 [[:name:]] 命名的“ASCII 类”包含在“字符类”中 (相当于 [:name:]) 6 [^[:name:]] 命名的“ASCII 类”不包含在“字符类”中 (相当于 [:^name:]) 7 [\p{Name}] 命名的“Unicode 类”包含在“字符类”中 (相当于 \p{Name}) 8 [^\p{Name}] 命名的“Unicode 类”不包含在“字符类”中 (相当于 \P{Name})

1.7.1 说明

1“字符类”取值如下(“字符类”包含“Perl类”、“ASCII类”、“Unicode类”): 2 x 单个字符 3 A-Z 字符范围(包含首尾字符) 4 \小写字母 Perl类 5 [:ASCII类名:] ASCII6 \p{Unicode脚本类名} Unicode类 (脚本类) 7 \pUnicode普通类名 Unicode类 (普通类) 8 9------------------------------ 10 11“Perl 类”取值如下: 12 13 \d 数字 (相当于 [0-9]) 14 \D 非数字 (相当于 [^0-9]) 15 \s 空白 (相当于 [\t\n\f\r ]) 16 \S 非空白 (相当于[^\t\n\f\r ]) 17 \w 单词字符 (相当于 [0-9A-Za-z_]) 18 \W 非单词字符 (相当于 [^0-9A-Za-z_]) 19 20------------------------------ 21 22ASCII 类”取值如下 23 24 [:alnum:] 字母数字 (相当于 [0-9A-Za-z]) 25 [:alpha:] 字母 (相当于 [A-Za-z]) 26 [:ascii:] ASCII 字符集 (相当于 [\x00-\x7F]) 27 [:blank:] 空白占位符 (相当于 [\t ]) 28 [:cntrl:] 控制字符 (相当于 [\x00-\x1F\x7F]) 29 [:digit:] 数字 (相当于 [0-9]) 30 [:graph:] 图形字符 (相当于 [!-~]) 31 [:lower:] 小写字母 (相当于 [a-z]) 32 [:print:] 可打印字符 (相当于 [ -~] 相当于 [ [:graph:]]) 33 [:punct:] 标点符号 (相当于 [!-/:-@[-反引号{-~]) 34 [:space:] 空白字符(相当于 [\t\n\v\f\r ]) 35 [:upper:] 大写字母(相当于 [A-Z]) 36 [:word:] 单词字符(相当于 [0-9A-Za-z_]) 37 [:xdigit:] 16 進制字符集(相当于 [0-9A-Fa-f]) 38 39------------------------------ 40 41“Unicode 类”取值如下---普通类: 42 43 C -其他- (other) 44 Cc 控制字符 (control) 45 Cf 格式 (format) 46 Co 私人使用区 (private use) 47 Cs 代理区 (surrogate) 48 L -字母- (letter) 49 Ll 小写字母 (lowercase letter) 50 Lm 修饰字母 (modifier letter) 51 Lo 其它字母 (other letter) 52 Lt 首字母大写字母 (titlecase letter) 53 Lu 大写字母 (uppercase letter) 54 M -标记- (mark) 55 Mc 间距标记 (spacing mark) 56 Me 关闭标记 (enclosing mark) 57 Mn 非间距标记 (non-spacing mark) 58 N -数字- (number) 59 Nd 十進制数字 (decimal number) 60 Nl 字母数字 (letter number) 61 No 其它数字 (other number) 62 P -标点- (punctuation) 63 Pc 连接符标点 (connector punctuation) 64 Pd 破折号标点符号 (dash punctuation) 65 Pe 关闭的标点符号 (close punctuation) 66 Pf 最后的标点符号 (final punctuation) 67 Pi 最初的标点符号 (initial punctuation) 68 Po 其他标点符号 (other punctuation) 69 Ps 开放的标点符号 (open punctuation) 70 S -符号- (symbol) 71 Sc 货币符号 (currency symbol) 72 Sk 修饰符号 (modifier symbol) 73 Sm 数学符号 (math symbol) 74 So 其他符号 (other symbol) 75 Z -分隔符- (separator) 76 Zl 行分隔符 (line separator) 77 Zp 段落分隔符 (paragraph separator) 78 Zs 空白分隔符 (space separator) 79 80------------------------------ 81 82“Unicode 类”取值如下---脚本类: 83 84 Arabic 阿拉伯文 85 Armenian 亚美尼亚文 86 Balinese 巴厘岛文 87 Bengali 孟加拉文 88 Bopomofo 汉语拼音字母 89 Braille 盲文 90 Buginese 布吉文 91 Buhid 布希德文 92 Canadian_Aboriginal 加拿大土著文 93 Carian 卡里亚文 94 Cham 占族文 95 Cherokee 切诺基文 96 Common 普通的,字符不是特定于一个脚本 97 Coptic 科普特文 98 Cuneiform 楔形文字 99 Cypriot 塞浦路斯文 100 Cyrillic 斯拉夫文 101 Deseret 犹他州文 102 Devanagari 梵文 103 Ethiopic 衣索比亚文 104 Georgian 格鲁吉亚文 105 Glagolitic 格拉哥里文 106 Gothic 哥特文 107 Greek 希腊 108 Gujarati 古吉拉特文 109 Gurmukhi 果鲁穆奇文 110 Han 汉文 111 Hangul 韩文 112 Hanunoo 哈鲁喏文 113 Hebrew 希伯来文 114 Hiragana 平假名(日语) 115 Inherited 继承前一个字符的脚本 116 Kannada 坎那达文 117 Katakana 片假名(日语) 118 Kayah_Li 克耶字母 119 Kharoshthi 卡罗须提文 120 Khmer 高棉文 121 Lao 老挝文 122 Latin 拉丁文 123 Lepcha 雷布查文 124 Limbu 林布文 125 Linear_B B类线形文字(古希腊) 126 Lycian 利西亚文 127 Lydian 吕底亚文 128 Malayalam 马拉雅拉姆文 129 Mongolian 蒙古文 130 Myanmar 缅甸文 131 New_Tai_Lue 新傣仂文 132 Nko Nko文 133 Ogham 欧甘文 134 Ol_Chiki 桑塔利文 135 Old_Italic 古意大利文 136 Old_Persian 古波斯文 137 Oriya 奥里亚文 138 Osmanya 奥斯曼亚文 139 Phags_Pa 八思巴文 140 Phoenician 腓尼基文 141 Rejang 拉让文 142 Runic 古代北欧文字 143 Saurashtra 索拉什特拉文(印度县城) 144 Shavian 萧伯纳文 145 Sinhala 僧伽罗文 146 Sundanese 巽他文 147 Syloti_Nagri 锡尔赫特文 148 Syriac 叙利亚文 149 Tagalog 塔加拉文 150 Tagbanwa 塔格巴努亚文 151 Tai_Le 德宏傣文 152 Tamil 泰米尔文 153 Telugu 泰卢固文 154 Thaana 塔安那文 155 Thai 泰文 156 Tibetan 藏文 157 Tifinagh 提非纳文 158 Ugaritic 乌加里特文 159 Vai 瓦伊文 160 Yi 彝文

1.8 注意

  • 对于 [a-z] 这样的正则表达式,如果要在 [] 中匹配 - ,可以将 - 放在 [] 的开头或结尾,例如 [-a-z] 或 [a-z-]   
  • 可以在 [] 中使用转义字符:\f、\t、\n、\r、\v、\377、\xFF、\x{10FFFF}、\\、\^、\$、\.、\*、\+、\?、\{、\}、\(、\)、\[、\]、\|(具体含义见上面的说明)   
  • 如果在正则表达式中使用了分组,则在执行正则替换的时候,“替换内容”中可以使用 $1、${1}、$name、${name} 这样的“分组引用符”获取相应的分组内容。其中 $0 代表整个匹配项,$1 代表第 1 个分组,$2 代表第 2 个分组  
  • 如果“分组引用符”是 $name 的形式,则在解析的时候,name 是取尽可能长的字符串,比如:$1x 相当于 ${1x},而不是${1}x,再比如:$10 相当于 ${10},而不是 ${1}0
  • 由于 $ 字符会被转义,所以要在“替换内容”中使用 $ 字符,可以用 \$ 代替
  • 上面介绍的正则表达式语法是”Perl 语法“,除了“Perl 语法”外,Go 语言中还有另一种”POSIX 语法“,”POSIX 语法“除了不能使用“Perl 类”之外,其它都一样

1.9 示例

1// 示例 2func main() { 3 text := `Hello 世界!123 Go.` 4 5 // 查找连续的小写字母 6 reg := regexp.MustCompile(`[a-z]+`) 7 fmt.Printf("%q\n", reg.FindAllString(text, -1)) 8 // ["ello" "o"] 9 10 // 查找连续的非小写字母 11 reg = regexp.MustCompile(`[^a-z]+`) 12 fmt.Printf("%q\n", reg.FindAllString(text, -1)) 13 // ["H" " 世界!123 G" "."] 14 15 // 查找连续的单词字母 16 reg = regexp.MustCompile(`[\w]+`) 17 fmt.Printf("%q\n", reg.FindAllString(text, -1)) 18 // ["Hello" "123" "Go"] 19 20 // 查找连续的非单词字母、非空白字符 21 reg = regexp.MustCompile(`[^\w\s]+`) 22 fmt.Printf("%q\n", reg.FindAllString(text, -1)) 23 // ["世界!" "."] 24 25 // 查找连续的大写字母 26 reg = regexp.MustCompile(`[[:upper:]]+`) 27 fmt.Printf("%q\n", reg.FindAllString(text, -1)) 28 // ["H" "G"] 29 30 // 查找连续的非 ASCII 字符 31 reg = regexp.MustCompile(`[[:^ascii:]]+`) 32 fmt.Printf("%q\n", reg.FindAllString(text, -1)) 33 // ["世界!"] 34 35 // 查找连续的标点符号 36 reg = regexp.MustCompile(`[\pP]+`) 37 fmt.Printf("%q\n", reg.FindAllString(text, -1)) 38 // ["!" "."] 39 40 // 查找连续的非标点符号字符 41 reg = regexp.MustCompile(`[\PP]+`) 42 fmt.Printf("%q\n", reg.FindAllString(text, -1)) 43 // ["Hello 世界" "123 Go"] 44 45 // 查找连续的汉字 46 reg = regexp.MustCompile(`[\p{Han}]+`) 47 fmt.Printf("%q\n", reg.FindAllString(text, -1)) 48 // ["世界"] 49 50 // 查找连续的非汉字字符 51 reg = regexp.MustCompile(`[\P{Han}]+`) 52 fmt.Printf("%q\n", reg.FindAllString(text, -1)) 53 // ["Hello " "!123 Go."] 54 55 // 查找 Hello 或 Go 56 reg = regexp.MustCompile(`Hello|Go`) 57 fmt.Printf("%q\n", reg.FindAllString(text, -1)) 58 // ["Hello" "Go"] 59 60 // 查找行首以 H 开头,以空格结尾的字符串 61 reg = regexp.MustCompile(`^H.*\s`) 62 fmt.Printf("%q\n", reg.FindAllString(text, -1)) 63 // ["Hello 世界!123 "] 64 65 // 查找行首以 H 开头,以空白结尾的字符串(非贪婪模式) 66 reg = regexp.MustCompile(`(?U)^H.*\s`) 67 fmt.Printf("%q\n", reg.FindAllString(text, -1)) 68 // ["Hello "] 69 70 // 查找以 hello 开头(忽略大小写),以 Go 结尾的字符串 71 reg = regexp.MustCompile(`(?i:^hello).*Go`) 72 fmt.Printf("%q\n", reg.FindAllString(text, -1)) 73 // ["Hello 世界!123 Go"] 74 75 // 查找 Go. 76 reg = regexp.MustCompile(`\QGo.\E`) 77 fmt.Printf("%q\n", reg.FindAllString(text, -1)) 78 // ["Go."] 79 80 // 查找从行首开始,以空格结尾的字符串(非贪婪模式) 81 reg = regexp.MustCompile(`(?U)^.* `) 82 fmt.Printf("%q\n", reg.FindAllString(text, -1)) 83 // ["Hello "] 84 85 // 查找以空格开头,到行尾结束,中间不包含空格字符串 86 reg = regexp.MustCompile(` [^ ]*$`) 87 fmt.Printf("%q\n", reg.FindAllString(text, -1)) 88 // [" Go."] 89 90 // 查找“单词边界”之间的字符串 91 reg = regexp.MustCompile(`(?U)\b.+\b`) 92 fmt.Printf("%q\n", reg.FindAllString(text, -1)) 93 // ["Hello" " 世界!" "123" " " "Go"] 94 95 // 查找连续 1 次到 4 次的非空格字符,并以 o 结尾的字符串 96 reg = regexp.MustCompile(`[^ ]{1,4}o`) 97 fmt.Printf("%q\n", reg.FindAllString(text, -1)) 98 // ["Hello" "Go"] 99 100 // 查找 Hello 或 Go 101 reg = regexp.MustCompile(`(?:Hell|G)o`) 102 fmt.Printf("%q\n", reg.FindAllString(text, -1)) 103 // ["Hello" "Go"] 104 105 // 查找 Hello 或 Go,替换为 Hellooo、Gooo 106 reg = regexp.MustCompile(`(?PHell|G)o`) 107 fmt.Printf("%q\n", reg.ReplaceAllString(text, "${n}ooo")) 108 // "Hellooo 世界!123 Gooo." 109 110 // 交换 Hello 和 Go 111 reg = regexp.MustCompile(`(Hello)(.*)(Go)`) 112 fmt.Printf("%q\n", reg.ReplaceAllString(text, "$3$2$1")) 113 // "Go 世界!123 Hello." 114 115 // 特殊字符的查找 116 reg = regexp.MustCompile(`[\f\t\n\r\v\123\x7F\x{10FFFF}\\\^\$\.\*\+\?\{\}\(\)\[\]\|]`) 117 fmt.Printf("%q\n", reg.ReplaceAllString("\f\t\n\r\v\123\x7F\U0010FFFF\\^$.*+?{}()[]|", "-")) 118 // "----------------------" 119}

2. Regexp 使用

1------------------------------------------------------------ 2 3// 判断在 b 中能否找到正则表达式 pattern 所匹配的子串 4// pattern:要查找的正则表达式 5// b:要在其中进行查找的 []byte 6// matched:返回是否找到匹配项 7// err:返回查找过程中遇到的任何错误 8// 此函数通过调用 Regexp 的方法实现 9func Match(pattern string, b []byte) (matched bool, err error) 10 11func main() { 12 fmt.Println(regexp.Match("H.* ", []byte("Hello World!"))) 13 // true 14} 15 16------------------------------------------------------------ 17 18// 判断在 r 中能否找到正则表达式 pattern 所匹配的子串 19// pattern:要查找的正则表达式 20// r:要在其中进行查找的 RuneReader 接口 21// matched:返回是否找到匹配项 22// err:返回查找过程中遇到的任何错误 23// 此函数通过调用 Regexp 的方法实现 24func MatchReader(pattern string, r io.RuneReader) (matched bool, err error) 25 26func main() { 27 r := bytes.NewReader([]byte("Hello World!")) 28 fmt.Println(regexp.MatchReader("H.* ", r)) 29 // true 30} 31 32------------------------------------------------------------ 33 34// 判断在 s 中能否找到正则表达式 pattern 所匹配的子串 35// pattern:要查找的正则表达式 36// r:要在其中进行查找的字符串 37// matched:返回是否找到匹配项 38// err:返回查找过程中遇到的任何错误 39// 此函数通过调用 Regexp 的方法实现 40func MatchString(pattern string, s string) (matched bool, err error) 41 42func main() { 43 fmt.Println(regexp.Match("H.* ", "Hello World!")) 44 // true 45} 46 47------------------------------------------------------------ 48 49// QuoteMeta 将字符串 s 中的“特殊字符”转换为其“转义格式” 50// 例如,QuoteMeta(`[foo]`)返回`\[foo\]`。 51// 特殊字符有:\.+*?()|[]{}^$ 52// 这些字符用于实现正则语法,所以当作普通字符使用时需要转换 53func QuoteMeta(s string) string 54 55func main() { 56 fmt.Println(regexp.QuoteMeta("(?P:Hello) [a-z]")) 57 // \(\?P:Hello\) \[a-z\] 58} 59 60------------------------------------------------------------ 61 62// Regexp 结构表示一个编译后的正则表达式 63// Regexp 的公开接口都是通过方法实现的 64// 多个 goroutine 并发使用一个 RegExp 是安全的 65type Regexp struct { 66 // 私有字段 67} 68 69// 通过 Complite、CompilePOSIX、MustCompile、MustCompilePOSIX 70// 四个函数可以创建一个 Regexp 对象 71 72------------------------------------------------------------ 73 74// Compile 用来解析正则表达式 expr 是否合法,如果合法,则返回一个 Regexp 对象 75// Regexp 对象可以在任意文本上执行需要的操作 76func Compile(expr string) (*Regexp, error) 77 78func main() { 79 reg, err := regexp.Compile(`\w+`) 80 fmt.Printf("%q,%v\n", reg.FindString("Hello World!"), err) 81 // "Hello", 82} 83 84------------------------------------------------------------ 85 86// CompilePOSIX 的作用和 Compile 一样 87// 不同的是,CompilePOSIX 使用 POSIX 语法, 88// 同时,它采用最左最长方式搜索, 89// 而 Compile 采用最左最短方式搜索 90// POSIX 语法不支持 Perl 的语法格式:\d、\D、\s、\S、\w、\W 91func CompilePOSIX(expr string) (*Regexp, error) 92 93func main() { 94 reg, err := regexp.CompilePOSIX(`[[:word:]]+`) 95 fmt.Printf("%q,%v\n", reg.FindString("Hello World!"), err) 96 // "Hello" 97} 98 99------------------------------------------------------------ 100 101// MustCompile 的作用和 Compile 一样 102// 不同的是,当正则表达式 str 不合法时,MustCompile 会抛出异常 103// 而 Compile 仅返回一个 error 值 104func MustCompile(str string) *Regexp 105 106func main() { 107 reg := regexp.MustCompile(`\w+`) 108 fmt.Println(reg.FindString("Hello World!")) 109 // Hello 110} 111 112------------------------------------------------------------ 113 114// MustCompilePOSIX 的作用和 CompilePOSIX 一样 115// 不同的是,当正则表达式 str 不合法时,MustCompilePOSIX 会抛出异常 116// 而 CompilePOSIX 仅返回一个 error 值 117func MustCompilePOSIX(str string) *Regexp 118 119func main() { 120 reg := regexp.MustCompilePOSIX(`[[:word:]].+ `) 121 fmt.Printf("%q\n", reg.FindString("Hello World!")) 122 // "Hello " 123} 124 125------------------------------------------------------------ 126 127// 在 b 中查找 re 中编译好的正则表达式,并返回第一个匹配的内容 128func (re *Regexp) Find(b []byte) []byte 129 130func main() { 131 reg := regexp.MustCompile(`\w+`) 132 fmt.Printf("%q", reg.Find([]byte("Hello World!"))) 133 // "Hello" 134} 135 136------------------------------------------------------------ 137 138// 在 s 中查找 re 中编译好的正则表达式,并返回第一个匹配的内容 139func (re *Regexp) FindString(s string) string 140 141func main() { 142 reg := regexp.MustCompile(`\w+`) 143 fmt.Println(reg.FindString("Hello World!")) 144 // "Hello" 145} 146 147------------------------------------------------------------ 148 149// 在 b 中查找 re 中编译好的正则表达式,并返回所有匹配的内容 150// {{匹配项}, {匹配项}, ...} 151// 只查找前 n 个匹配项,如果 n < 0,则查找所有匹配项 152func (re *Regexp) FindAll(b []byte, n int) [][]byte 153 154func main() { 155 reg := regexp.MustCompile(`\w+`) 156 fmt.Printf("%q", reg.FindAll([]byte("Hello World!"), -1)) 157 // ["Hello" "World"] 158} 159 160------------------------------------------------------------ 161 162// 在 s 中查找 re 中编译好的正则表达式,并返回所有匹配的内容 163// {匹配项, 匹配项, ...} 164// 只查找前 n 个匹配项,如果 n < 0,则查找所有匹配项 165func (re *Regexp) FindAllString(s string, n int) []string 166 167func main() { 168 reg := regexp.MustCompile(`\w+`) 169 fmt.Printf("%q", reg.FindAllString("Hello World!", -1)) 170 // ["Hello" "World"] 171} 172 173------------------------------------------------------------ 174 175// 在 b 中查找 re 中编译好的正则表达式,并返回第一个匹配的位置 176// {起始位置, 结束位置} 177func (re *Regexp) FindIndex(b []byte) (loc []int) 178 179func main() { 180 reg := regexp.MustCompile(`\w+`) 181 fmt.Println(reg.FindIndex([]byte("Hello World!"))) 182 // [0 5] 183} 184 185------------------------------------------------------------ 186 187// 在 s 中查找 re 中编译好的正则表达式,并返回第一个匹配的位置 188// {起始位置, 结束位置} 189func (re *Regexp) FindStringIndex(s string) (loc []int) 190 191func main() { 192 reg := regexp.MustCompile(`\w+`) 193 fmt.Println(reg.FindStringIndex("Hello World!")) 194 // [0 5] 195} 196 197------------------------------------------------------------ 198 199// 在 r 中查找 re 中编译好的正则表达式,并返回第一个匹配的位置 200// {起始位置, 结束位置} 201func (re *Regexp) FindReaderIndex(r io.RuneReader) (loc []int) 202 203func main() { 204 r := bytes.NewReader([]byte("Hello World!")) 205 reg := regexp.MustCompile(`\w+`) 206 fmt.Println(reg.FindReaderIndex(r)) 207 // [0 5] 208} 209 210------------------------------------------------------------ 211 212// 在 b 中查找 re 中编译好的正则表达式,并返回所有匹配的位置 213// {{起始位置, 结束位置}, {起始位置, 结束位置}, ...} 214// 只查找前 n 个匹配项,如果 n < 0,则查找所有匹配项 215func (re *Regexp) FindAllIndex(b []byte, n int) [][]int 216 217func main() { 218 reg := regexp.MustCompile(`\w+`) 219 fmt.Println(reg.FindAllIndex([]byte("Hello World!"), -1)) 220 // [[0 5] [6 11]] 221} 222 223------------------------------------------------------------ 224 225// 在 s 中查找 re 中编译好的正则表达式,并返回所有匹配的位置 226// {{起始位置, 结束位置}, {起始位置, 结束位置}, ...} 227// 只查找前 n 个匹配项,如果 n < 0,则查找所有匹配项 228func (re *Regexp) FindAllStringIndex(s string, n int) [][]int 229 230func main() { 231 reg := regexp.MustCompile(`\w+`) 232 fmt.Println(reg.FindAllStringIndex("Hello World!", -1)) 233 // [[0 5] [6 11]] 234} 235 236------------------------------------------------------------ 237 238// 在 b 中查找 re 中编译好的正则表达式,并返回第一个匹配的内容 239// 同时返回子表达式匹配的内容 240// {{完整匹配项}, {子匹配项}, {子匹配项}, ...} 241func (re *Regexp) FindSubmatch(b []byte) [][]byte 242 243func main() { 244 reg := regexp.MustCompile(`(\w)(\w)+`) 245 fmt.Printf("%q", reg.FindSubmatch([]byte("Hello World!"))) 246 // ["Hello" "H" "o"] 247} 248 249------------------------------------------------------------ 250 251// 在 s 中查找 re 中编译好的正则表达式,并返回第一个匹配的内容 252// 同时返回子表达式匹配的内容 253// {完整匹配项, 子匹配项, 子匹配项, ...} 254func (re *Regexp) FindStringSubmatch(s string) []string 255 256func main() { 257 reg := regexp.MustCompile(`(\w)(\w)+`) 258 fmt.Printf("%q", reg.FindStringSubmatch("Hello World!")) 259 // ["Hello" "H" "o"] 260} 261 262------------------------------------------------------------ 263 264// 在 b 中查找 re 中编译好的正则表达式,并返回所有匹配的内容 265// 同时返回子表达式匹配的内容 266// { 267// {{完整匹配项}, {子匹配项}, {子匹配项}, ...}, 268// {{完整匹配项}, {子匹配项}, {子匹配项}, ...}, 269// ... 270// } 271func (re *Regexp) FindAllSubmatch(b []byte, n int) [][][]byte 272 273func main() { 274 reg := regexp.MustCompile(`(\w)(\w)+`) 275 fmt.Printf("%q", reg.FindAllSubmatch([]byte("Hello World!"), -1)) 276 // [["Hello" "H" "o"] ["World" "W" "d"]] 277} 278 279------------------------------------------------------------ 280 281// 在 s 中查找 re 中编译好的正则表达式,并返回所有匹配的内容 282// 同时返回子表达式匹配的内容 283// { 284// {完整匹配项, 子匹配项, 子匹配项, ...}, 285// {完整匹配项, 子匹配项, 子匹配项, ...}, 286// ... 287// } 288// 只查找前 n 个匹配项,如果 n < 0,则查找所有匹配项 289func (re *Regexp) FindAllStringSubmatch(s string, n int) [][]string 290 291func main() { 292 reg := regexp.MustCompile(`(\w)(\w)+`) 293 fmt.Printf("%q", reg.FindAllStringSubmatch("Hello World!", -1)) 294 // [["Hello" "H" "o"] ["World" "W" "d"]] 295} 296 297------------------------------------------------------------ 298 299// 在 b 中查找 re 中编译好的正则表达式,并返回第一个匹配的位置 300// 同时返回子表达式匹配的位置 301// {完整项起始, 完整项结束, 子项起始, 子项结束, 子项起始, 子项结束, ...} 302func (re *Regexp) FindSubmatchIndex(b []byte) []int 303 304func main() { 305 reg := regexp.MustCompile(`(\w)(\w)+`) 306 fmt.Println(reg.FindSubmatchIndex([]byte("Hello World!"))) 307 // [0 5 0 1 4 5] 308} 309 310------------------------------------------------------------ 311 312// 在 s 中查找 re 中编译好的正则表达式,并返回第一个匹配的位置 313// 同时返回子表达式匹配的位置 314// {完整项起始, 完整项结束, 子项起始, 子项结束, 子项起始, 子项结束, ...} 315func (re *Regexp) FindStringSubmatchIndex(s string) []int 316 317func main() { 318 reg := regexp.MustCompile(`(\w)(\w)+`) 319 fmt.Println(reg.FindStringSubmatchIndex("Hello World!")) 320 // [0 5 0 1 4 5] 321} 322 323------------------------------------------------------------ 324 325// 在 r 中查找 re 中编译好的正则表达式,并返回第一个匹配的位置 326// 同时返回子表达式匹配的位置 327// {完整项起始, 完整项结束, 子项起始, 子项结束, 子项起始, 子项结束, ...} 328func (re *Regexp) FindReaderSubmatchIndex(r io.RuneReader) []int 329 330func main() { 331 r := bytes.NewReader([]byte("Hello World!")) 332 reg := regexp.MustCompile(`(\w)(\w)+`) 333 fmt.Println(reg.FindReaderSubmatchIndex(r)) 334 // [0 5 0 1 4 5] 335} 336 337------------------------------------------------------------ 338 339// 在 b 中查找 re 中编译好的正则表达式,并返回所有匹配的位置 340// 同时返回子表达式匹配的位置 341// { 342// {完整项起始, 完整项结束, 子项起始, 子项结束, 子项起始, 子项结束, ...}, 343// {完整项起始, 完整项结束, 子项起始, 子项结束, 子项起始, 子项结束, ...}, 344// ... 345// } 346// 只查找前 n 个匹配项,如果 n < 0,则查找所有匹配项 347func (re *Regexp) FindAllSubmatchIndex(b []byte, n int) [][]int 348 349func main() { 350 reg := regexp.MustCompile(`(\w)(\w)+`) 351 fmt.Println(reg.FindAllSubmatchIndex([]byte("Hello World!"), -1)) 352 // [[0 5 0 1 4 5] [6 11 6 7 10 11]] 353} 354 355------------------------------------------------------------ 356 357// 在 s 中查找 re 中编译好的正则表达式,并返回所有匹配的位置 358// 同时返回子表达式匹配的位置 359// { 360// {完整项起始, 完整项结束, 子项起始, 子项结束, 子项起始, 子项结束, ...}, 361// {完整项起始, 完整项结束, 子项起始, 子项结束, 子项起始, 子项结束, ...}, 362// ... 363// } 364// 只查找前 n 个匹配项,如果 n < 0,则查找所有匹配项 365func (re *Regexp) FindAllStringSubmatchIndex(s string, n int) [][]int 366 367func main() { 368 reg := regexp.MustCompile(`(\w)(\w)+`) 369 fmt.Println(reg.FindAllStringSubmatchIndex("Hello World!", -1)) 370 // [[0 5 0 1 4 5] [6 11 6 7 10 11]] 371} 372 373------------------------------------------------------------ 374 375// 将 template 的内容经过处理后,追加到 dst 的尾部。 376// template 中要有 $1、$2、${name1}、${name2} 这样的“分组引用符” 377// match 是由 FindSubmatchIndex 方法返回的结果,里面存放了各个分组的位置信息 378// 如果 template 中有“分组引用符”,则以 match 为标准, 379// 在 src 中取出相应的子串,替换掉 template 中的 $1、$2 等引用符号。 380func (re *Regexp) Expand(dst []byte, template []byte, src []byte, match []int) []byte 381 382func main() { 383 reg := regexp.MustCompile(`(\w+),(\w+)`) 384 src := []byte("Golang,World!") // 源文本 385 dst := []byte("Say: ") // 目标文本 386 template := []byte("Hello $1, Hello $2") // 模板 387 match := reg.FindSubmatchIndex(src) // 解析源文本 388 // 填写模板,并将模板追加到目标文本中 389 fmt.Printf("%q", reg.Expand(dst, template, src, match)) 390 // "Say: Hello Golang, Hello World" 391} 392 393------------------------------------------------------------ 394 395// 功能同 Expand 一样,只不过参数换成了 string 类型 396func (re *Regexp) ExpandString(dst []byte, template string, src string, match []int) []byte 397 398func main() { 399 reg := regexp.MustCompile(`(\w+),(\w+)`) 400 src := "Golang,World!" // 源文本 401 dst := []byte("Say: ") // 目标文本(可写) 402 template := "Hello $1, Hello $2" // 模板 403 match := reg.FindStringSubmatchIndex(src) // 解析源文本 404 // 填写模板,并将模板追加到目标文本中 405 fmt.Printf("%q", reg.ExpandString(dst, template, src, match)) 406 // "Say: Hello Golang, Hello World" 407} 408 409------------------------------------------------------------ 410 411// LiteralPrefix 返回所有匹配项都共同拥有的前缀(去除可变元素) 412// prefix:共同拥有的前缀 413// complete:如果 prefix 就是正则表达式本身,则返回 true,否则返回 false 414func (re *Regexp) LiteralPrefix() (prefix string, complete bool) 415 416func main() { 417 reg := regexp.MustCompile(`Hello[\w\s]+`) 418 fmt.Println(reg.LiteralPrefix()) 419 // Hello false 420 reg = regexp.MustCompile(`Hello`) 421 fmt.Println(reg.LiteralPrefix()) 422 // Hello true 423} 424 425------------------------------------------------------------ 426 427// 切换到“贪婪模式” 428func (re *Regexp) Longest() 429 430func main() { 431 text := `Hello World, 123 Go!` 432 pattern := `(?U)H[\w\s]+o` // 正则标记“非贪婪模式”(?U) 433 reg := regexp.MustCompile(pattern) 434 fmt.Printf("%q\n", reg.FindString(text)) 435 // Hello 436 reg.Longest() // 切换到“贪婪模式” 437 fmt.Printf("%q\n", reg.FindString(text)) 438 // Hello Wo 439} 440 441------------------------------------------------------------ 442 443// 判断在 b 中能否找到匹配项 444func (re *Regexp) Match(b []byte) bool 445 446func main() { 447 b := []byte(`Hello World`) 448 reg := regexp.MustCompile(`Hello\w+`) 449 fmt.Println(reg.Match(b)) 450 // false 451 reg = regexp.MustCompile(`Hello[\w\s]+`) 452 fmt.Println(reg.Match(b)) 453 // true 454} 455 456------------------------------------------------------------ 457 458// 判断在 r 中能否找到匹配项 459func (re *Regexp) MatchReader(r io.RuneReader) bool 460 461func main() { 462 r := bytes.NewReader([]byte(`Hello World`)) 463 reg := regexp.MustCompile(`Hello\w+`) 464 fmt.Println(reg.MatchReader(r)) 465 // false 466 r.Seek(0, 0) 467 reg = regexp.MustCompile(`Hello[\w\s]+`) 468 fmt.Println(reg.MatchReader(r)) 469 // true 470} 471 472------------------------------------------------------------ 473 474// 判断在 s 中能否找到匹配项 475func (re *Regexp) MatchString(s string) bool 476 477func main() { 478 s := `Hello World` 479 reg := regexp.MustCompile(`Hello\w+`) 480 fmt.Println(reg.MatchString(s)) 481 // false 482 reg = regexp.MustCompile(`Hello[\w\s]+`) 483 fmt.Println(reg.MatchString(s)) 484 // true 485} 486 487------------------------------------------------------------ 488 489// 统计正则表达式中的分组个数(不包括“非捕获的分组”) 490func (re *Regexp) NumSubexp() int 491 492func main() { 493 reg := regexp.MustCompile(`(?U)(?:Hello)(\s+)(\w+)`) 494 fmt.Println(reg.NumSubexp()) 495 // 2 496} 497 498------------------------------------------------------------ 499 500// 在 src 中搜索匹配项,并替换为 repl 指定的内容 501// 全部替换,并返回替换后的结果 502func (re *Regexp) ReplaceAll(src, repl []byte) []byte 503 504func main() { 505 b := []byte("Hello World, 123 Go!") 506 reg := regexp.MustCompile(`(Hell|G)o`) 507 rep := []byte("${1}ooo") 508 fmt.Printf("%q\n", reg.ReplaceAll(b, rep)) 509 // "Hellooo World, 123 Gooo!" 510} 511 512------------------------------------------------------------ 513 514// 在 src 中搜索匹配项,并替换为 repl 指定的内容 515// 全部替换,并返回替换后的结果 516func (re *Regexp) ReplaceAllString(src, repl string) string 517 518func main() { 519 s := "Hello World, 123 Go!" 520 reg := regexp.MustCompile(`(Hell|G)o`) 521 rep := "${1}ooo" 522 fmt.Printf("%q\n", reg.ReplaceAllString(s, rep)) 523 // "Hellooo World, 123 Gooo!" 524} 525 526------------------------------------------------------------ 527 528// 在 src 中搜索匹配项,并替换为 repl 指定的内容 529// 如果 repl 中有“分组引用符”($1、$name),则将“分组引用符”当普通字符处理 530// 全部替换,并返回替换后的结果 531func (re *Regexp) ReplaceAllLiteral(src, repl []byte) []byte 532 533func main() { 534 b := []byte("Hello World, 123 Go!") 535 reg := regexp.MustCompile(`(Hell|G)o`) 536 rep := []byte("${1}ooo") 537 fmt.Printf("%q\n", reg.ReplaceAllLiteral(b, rep)) 538 // "${1}ooo World, 123 ${1}ooo!" 539} 540 541------------------------------------------------------------ 542 543// 在 src 中搜索匹配项,并替换为 repl 指定的内容 544// 如果 repl 中有“分组引用符”($1、$name),则将“分组引用符”当普通字符处理 545// 全部替换,并返回替换后的结果 546func (re *Regexp) ReplaceAllLiteralString(src, repl string) string 547 548func main() { 549 s := "Hello World, 123 Go!" 550 reg := regexp.MustCompile(`(Hell|G)o`) 551 rep := "${1}ooo" 552 fmt.Printf("%q\n", reg.ReplaceAllLiteralString(s, rep)) 553 // "${1}ooo World, 123 ${1}ooo!" 554} 555 556------------------------------------------------------------ 557 558// 在 src 中搜索匹配项,然后将匹配的内容经过 repl 处理后,替换 src 中的匹配项 559// 如果 repl 的返回值中有“分组引用符”($1、$name),则将“分组引用符”当普通字符处理 560// 全部替换,并返回替换后的结果 561func (re *Regexp) ReplaceAllFunc(src []byte, repl func([]byte) []byte) []byte 562 563func main() { 564 s := []byte("Hello World!") 565 reg := regexp.MustCompile("(H)ello") 566 rep := []byte("$0$1") 567 fmt.Printf("%s\n", reg.ReplaceAll(s, rep)) 568 // HelloH World! 569 570 fmt.Printf("%s\n", reg.ReplaceAllFunc(s, 571 func(b []byte) []byte { 572 rst := []byte{} 573 rst = append(rst, b...) 574 rst = append(rst, "$1"...) 575 return rst 576 })) 577 // Hello$1 World! 578} 579k 580------------------------------------------------------------ 581 582// 在 src 中搜索匹配项,然后将匹配的内容经过 repl 处理后,替换 src 中的匹配项 583// 如果 repl 的返回值中有“分组引用符”($1、$name),则将“分组引用符”当普通字符处理 584// 全部替换,并返回替换后的结果 585func (re *Regexp) ReplaceAllStringFunc(src string, repl func(string) string) string 586 587func main() { 588 s := "Hello World!" 589 reg := regexp.MustCompile("(H)ello") 590 rep := "$0$1" 591 fmt.Printf("%s\n", reg.ReplaceAllString(s, rep)) 592 // HelloH World! 593 fmt.Printf("%s\n", reg.ReplaceAllStringFunc(s, 594 func(b string) string { 595 return b + "$1" 596 })) 597 // Hello$1 World! 598} 599 600------------------------------------------------------------ 601 602// 在 s 中搜索匹配项,并以匹配项为分割符,将 s 分割成多个子串 603// 最多分割出 n 个子串,第 n 个子串不再进行分割 604// 如果 n < 0,则分割所有子串 605// 返回分割后的子串列表 606func (re *Regexp) Split(s string, n int) []string 607 608func main() { 609 s := "Hello World\tHello\nGolang" 610 reg := regexp.MustCompile(`\s`) 611 fmt.Printf("%q\n", reg.Split(s, -1)) 612 // ["Hello" "World" "Hello" "Golang"] 613} 614 615------------------------------------------------------------ 616 617// 返回 re 中的“正则表达式”字符串 618func (re *Regexp) String() string 619 620func main() { 621 re := regexp.MustCompile("Hello.*$") 622 fmt.Printf("%s\n", re.String()) 623 // Hello.*$ 624} 625 626------------------------------------------------------------ 627 628// 返回 re 中的分组名称列表,未命名的分组返回空字符串 629// 返回值[0] 为整个正则表达式的名称 630// 返回值[1] 是分组 1 的名称 631// 返回值[2] 是分组 2 的名称 632// …… 633func (re *Regexp) SubexpNames() []string 634 635func main() { 636 re := regexp.MustCompile("(?PHello) (World)") 637 fmt.Printf("%q\n", re.SubexpNames()) 638 // ["" "Name1" ""] 639}

3. 参考文献

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )

Golang(四)正则表达式使用 - HelloWorld