5

从 Golang 正则式讲起

 2 years ago
source link: https://hedzr.com/golang/regexp/lets-talk-about-golang-regexp/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

从 Golang 正则式讲起

介绍正则表达式我之了解与理解 …

9 分钟阅读

  1. >
  2. Golang >
  3. Regexp >
  4. 从 Golang 正则式讲起

Golang 正则式语法概述Permalink

Golang 实际上支持两种正则式语法,其一为标配语法,这是源于 RE2 的语法规则,稍后将会完整阐释,其二为 POSIX ERE 规范,这种规范源于 Perl 正则式规范但有所变化,此规范本文内不做介绍。

ExamplesPermalink

POSIX 方式Permalink

POSIX ERE 规范,也就是 egrep 正则式语法,在 Linux/macOS 中可以这样获得:

egrep 'a*b?c'
grep -E 'a(.*?)c'

详细介绍这种所谓的扩展的正则式语法,不是本文的目标,故而略过。

golang 中可以使用 CompilePOSIXMustCompilePOSIX,简短示例如下:

// remove new line chars
reg, _ := regexp.CompilePOSIX("\r\n|\r|\n")
inner = reg.ReplaceAllString(inner, "")

RE2 方式Permalink

大多数情况下,我们可能都是采用 Golang 的基本方式,也就是 RE2 规范来做正则式计算,一般是通过 func Compile 或者 func MustCompile 来编译一个正则式模板:

package main

import (
	"fmt"
	"regexp"
)

func main() {
	// Compile the expression once, usually at init time.
	// Use raw strings to avoid having to quote the backslashes.
	var validID = regexp.MustCompile(`^[a-z]+\[[0-9]+\]$`)

	fmt.Println(validID.MatchString("adam[23]"))
	fmt.Println(validID.MatchString("eve[7]"))
	fmt.Println(validID.MatchString("Job[48]"))
	fmt.Println(validID.MatchString("snakey"))
}

// Output:
// 
// true
// true
// false
// false

RE2 语法在 https://golang.org/s/re2syntax 有完整的描述,本文基于该描述进行阐释。它的一个微有节选的易读版本在 https://pkg.go.dev/regexp/syntax 可以访问,两者可以同时对照以便阅读和相互印证。

注意此 RE2微软的 RE2 相同而又有所不同。简而言之,RE2微软的 RE2 的 Golang 实现版本,由 Google 官方进行维护。

区别Permalink

RE2 和 POSIX/Perl 兼容的正则式的区别较为难以叙述,其中一个原因在于 Perl 正则式自己曾经发生过演变与分叉,形成了所谓古典的 Perl regexp 和现代的 Perl regexp 的区别,此外,POSIX regexp 和 RE2 也略有区别,这主要表现在 submatch 的处理上,POSIX 将会尽量返回更长版本(默认为贪婪模式),而 RE2 则会返回尽可能短的版本(默认为非贪婪模式)。

package main

import (
	"fmt"
	"regexp"
)

func main() {
	pattern := "(foo|foobar)"
	str := []byte("foobarbaz")

	rPCRE, _ := regexp.Compile(pattern)
	rPOSIX, _ := regexp.CompilePOSIX(pattern)

	matchesPCRE := rPCRE.Find(str)
	fmt.Println("RE2: ", string(matchesPCRE))
	// prints "foo"

	matchesPOSIX := rPOSIX.Find(str)
	fmt.Println("POSIX: ", string(matchesPOSIX))
	// prints "foobar"
}

注意,这个示例源于 playground,但源码中的命名有一个问题:PCRE 是 Perl Compatible Regular Expressions 的意思,在一个很大的程度上它几乎也是 POSIX Regular Expressions 的代名词。

所以 matchesPCRE 变量名应该命名为 matchesRE2 才是正确的。

Find(All)?(String)?(Submatch)?(Index)?Permalink

所有关于 Golang regexp 包的介绍都不能少却这一小节。regexp 包为正则表达式提供了 16 个查找方法,它们的命名具有一定规律,其格式为 Find(All)?(String)?(Submatch)?(Index)?

其中的名称短语具有如下特点:

  • All:它会继续查找非重叠的后续的字符串,返回全部匹配结果为一个 slice
  • String:入参将会采用 string 类型,否则你需要提供 []byte
  • Submatch:在返回匹配结果的同时,也返回子表达式(Capturing Group)的匹配项
  • Index:

正则式简史Permalink

发觉有必要简述一下正则式的各种分支版本。

正则表达式的 POSIX 规范,分为基本型正则表达式(Basic Regular Expression,BRE)和扩展型正则表达式(Extended Regular Express,ERE)两大流派。在兼容 POSIX 的 UNIX 系统上,grep 和 egrep 之类的工具都遵循 POSIX 规范,一些数据库系统中的正则表达式也匹配 POSIX 规范。grep、vi、sed 都属于 BRE,是历史最早的正则表达式,因此元字符必须转译之后才具有特殊含义。egrep、awk 则属于 ERE,元字符不用转译。(源自 Wiki

Perl 的正则式解析器原采用 PCRE,但在分叉之后就形成了 egrep 和 pgrep 两种版本。PCRE 继续单独开发,形成了 Extended RE(ERE,egrep),Perl 自己维护自身的正则式形成了 Perl RE 语法(pgrep)。

macOS 上的 grep 不支持 pgrep 格式,因此跨平台有效的 RE Pattern 最好以 ERE 风格来编写,即采用 POSIX RE 标准。

实际上,POSIX 标准中还有一种标准型正则表达式(Simple RE,SRE)。不过由于其简单性,没有什么实作案例,通常也不推荐采用这种规范。

在现代浏览器应用开发中,Javascript 也通过 ECMA 标准维护着一套正则式规范。ECMAScript 中的正则式基本上是 POSIX RE 的一种拓展版本。不过要由我个人观点来看,渐入歧途吧。

但 RE2 当然是一个不同的家伙。

微软的 RE2 原出于微软中国研究院,刚发布时名为 greta,名声相当嘹亮,性能优秀,一出品时性能是当时的正则式引擎(boost.regexp)的 7 倍以上,着实是有相当的风头。我之所以对其印象如此深刻,是因为这家伙是 C++ 模板元编程实现的,质量很好(当然,写这类型的类库的人往往都很变态,所以可读性不要有什么期待)

一晃也是二十年过去了,真是物是人非啊。现在你很难找到 greta 的源流了,所以说时间真的可以湮没一切,即使有北极磁带备份又如何,greta 甚至不值得一个维基词条,这既是一个悲哀,又是某种必然。

如果想了解正规表达式,可以阅读维基词条:

如果想了解 PCRE 语法,请查阅 Regular expression - Wikipedia ,这里完整但缺乏样例。

如果想了解 Greta/RE2 语法,可以查阅 微软的 RE2 ,也是完整但缺乏样例。

如果想了解 Golang 标配的 RE2 语法,请注意它和 微软的 RE2 并无区别,但你当然可以在这里进行查阅:

Golang 正则式语法一览Permalink

本章节以 Syntax · google/re2 Wiki 为参考基准。

https://pkg.go.dev/regexp/syntax 更简单明快一些,剔除了不支持的条目。

单个字符(Single character)Permalink

kinds of single-character expressions examples 匹配任意一个字符,如果设置 s = true,则可以匹配换行符 . 匹配 “字符类” 中的一个字符,即匹配 x, y 或 z [xyz] 不匹配 “字符类” 中的任一字符,即不匹配 x,y 或 z [^xyz] 匹配 “Perl类” 中的一个字符 (link) \d 不匹配 “Perl类” 中的任一字符 \D 匹配 “ASCII类” 中的一个字符 (link) [[:alpha:]] 不匹配 “ASCII类” 中的任一字符 [[:^alpha:]] 匹配 “Unicode 字符类” (one-letter name) 的一个字符 \pN 匹配 “Unicode 字符类” 的一个字符 \p{Greek} 不匹配 “Unicode 字符类” (one-letter name) 的任一字符 \PN 不匹配 “Unicode 字符类” 的任一字符 \P{Greek}

  1. 字符类在后文中进行解释。

复合匹配/结合(Composite)Permalink

Composites xy 匹配 xy(x 之后跟随着 yx|y 匹配 x 或者 y (x 相对更优先)

重复(Repetitions)Permalink

Repetitions x* 匹配零个或多个 x,优先匹配更多(贪婪) x+ 匹配一个或多个 x,优先匹配更多(贪婪) x? 匹配零个或一个 x,优先匹配一个(贪婪) x{n,m} 匹配 nmx,优先匹配更多(贪婪) x{n,} 匹配 n 个或多个 x,优先匹配更多(贪婪) x{n} 精确地匹配 nx x*? 匹配零个或多个 x,优先匹配更少(非贪婪模式) x+? 匹配一个或多个 x,优先匹配更少(非贪婪模式) x?? 匹配零个或一个 x,优先匹配零个(非贪婪模式) x{n,m}? 匹配 nmx,优先匹配更少(非贪婪模式) x{n,}? 匹配 n 个或多个 x,优先匹配更少(非贪婪模式) x{n}? 精确地匹配 nx(非贪婪模式) x{} (等价于 x*)(不支持)VIM x{-} (等价于 x*?)(不支持)VIM x{-n} (等价于 x{n}?)(不支持)VIM x= (等价于 x?)(不支持)VIM

启动限制:计数形式 x{n,m}、x{n,} 和 x{n} 最小或最大重复个数不能超过 1000。 无限制的重复不受此限制约束。

所有格重复 x*+ 匹配零个或任意个 x,所有格(不支持) x++ 匹配至少一个 x,所有格(不支持) x?+ 匹配零个或一个 x,所有格(不支持) x {n,m} + 匹配 n…或 m 个 x,所有格(不支持) x{n,}+ 匹配至少 n 个 x,所有格(不支持) x{n}+ 匹配确定的 n 个 x,所有格(不支持)

分组(Grouping)Permalink

Grouping (re) 编号捕获组(子匹配) (?P<name>re) 命名 & 编号捕获组(子匹配) (?<name>re) 命名 & 编号捕获组(子匹配)(不支持) (?'name're) 命名 & 编号捕获组(子匹配)(不支持) (?:re) 非捕获组 (?flags) 在当前组中设置标志;非捕获 (?flags:re) 在表达式中设置标志;非捕获 (?#text) 注释(不支持) (?|x|y|z) 分支编号重置(不支持) (?>re) 表达式所有格匹配 (不支持) re@> 表达式所有格匹配(不支持)VIM %(re) 非捕获组(不支持) VIM

上表中的 flags 可以是:

Flags i 不区分大小写(默认为 false) m 多行模式: ^$ 匹配行首/尾,以及文本开头/结尾(默认为 false) s 允许 . 匹配 \n (默认为 false) U 非贪婪模式:以 x*? 替换 x*x+? 替换 x+ 等(默认为 false)

标记语法为 xyz (已设置)或 -xyz (清除)或 xy-z (设置为 xy,清除 z)。

Flag syntax is xyz (set) or -xyz (clear) or xy-z (set xy, clear z).

空字符串Permalink

Empty strings ^ 文本开始或行首(m = true) $ 文本开始或行首(m = true) \A 文本开头 \b 匹配 ASCII 单词边界(\w 表示一端,\W、\A 或 \z 表示另一端) \B 匹配非 ASCII 单词边界 \g 匹配正在搜索的从属文本开头(不支持) PCRE \G 匹配上一个匹配的结尾(不支持) PERL \Z 匹配必须出现在文本末尾,或在文本末尾换行前的位置(不支持) \z 匹配文本末尾 (?=re) 前向肯定界定符(不支持) (?!re) 前向否定界定符(不支持) (?<=re) 后向肯定界定符(不支持) (?<!re) 后向否定界定符(不支持) re& 前向肯定界定符(不支持)VIM re@= 前向肯定界定符(不支持)VIM re@! 前向否定界定符(不支持)VIM re@<= 后向肯定界定符(不支持)VIM re@<! 后向否定界定符(不支持)VIM \zs 设置匹配开始(同 \K)(不支持) VIM \ze 设置匹配结尾(不支持) VIM \%^ 匹配文件开头(不支持) VIM \%$ 匹配文件结尾(不支持) VIM \%V 在屏幕上匹配(不支持)VIM \%# 从光标位置匹配(不支持) VIM \%'m 在标记 m 的位置匹配(不支持) VIM \%23l 在第 23 行匹配(不支持)VIM \%23c 在第 23 列匹配(不支持)VIM \%23v 在虚拟第 23 列匹配(不支持)VIM

转义序列Permalink

Escape sequences \a 报警符 bell (≡ \007) \f 换页符 form feed (≡ \014) \t 水平制表符 horizontal tab (≡ \011) \n 换行符 newline (≡ \012) \r 回车符 carriage return (≡ \015) \v 垂直制表符 vertical tab character (≡ \013) \* 字面量 *, 匹配任意标点字符 * \123 匹配八进制字符代码(最多三位) \x7F 匹配十六进制字符代码(最多两位) \x{10FFFF} 匹配十六进制字符代码 \C 匹配单字节,即使在 UTF-8 模式下 \Q...\E 匹配文本 ... ,即使 ... 中包含标点 \1 匹配反向引用(不支持) \b 匹配退格 (不支持)(使用 \010\cK 匹配控制字符 ^K (不支持)(使用 \001 等) \e 匹配转义符 (不支持)(使用 \033\g1 匹配反向引用(不支持) \g{1} 匹配反向引用(不支持) \g{+1} 匹配反向引用(不支持) \g{-1} 匹配反向引用(不支持) \g{name} 匹配已命名反向引用(不支持) \g<name> 匹配子例程调用(不支持) \g'name' 匹配子例程调用(不支持) \k<name> 匹配已命名反向引用(不支持) \k'name' 匹配已命名反向引用(不支持) \lX 匹配小写 X(不支持) \ux 匹配大写 x(不支持) \L...\E 匹配小写文本 ... (不支持) \K 重置 $0 开头(不支持) \N{name} 匹配已命名 Unicode 字符(不支持) \R 匹配换行符(不支持) \U...\E 匹配大写文本 ... (不支持) \X 匹配扩展 Unicode 序列(不支持) \%d123 匹配十进制字符 123(不支持) VIM \%xFF 匹配十六进制字符 FF (不支持) VIM \%o123 匹配八进制字符 123(不支持) VIM \%u1234 匹配 Unicode 字符 0x1234(不支持)VIM \%U12345678 匹配 Unicode 字符 0x12345678(不支持)VIM

字符组元素(字符类)Permalink

Character class elements x 单个字符 A-Z 字符范围(含) \d 匹配 Perl 字符类 [:foo:] 匹配 ASCII 字符类 foo \p{Foo} 匹配 Unicode 字符类 Foo \pF 匹配 Unicode 字符类 F(单字母名称)

作为字符类元素命名的字符组Permalink

Named character classes as character class elements [\d] 数字字符 (≡ \d) [^\d] 非数字字符 (≡ \D) [\D] 非数字字符 (≡ \D) [^\D] 非非数字字符、即数字字符 (≡ \d) [[:name:]] 匹配在字符类内部命名的 ASCII 类 (≡ [:name:]) [^[:name:]] 匹配在排除型字符类内部命名的 ASCII 类 (≡ [:^name:]) [\p{Name}] 匹配在字符类内部命名的 Unicode 属性 (≡ \p{Name}) [^\p{Name}] 匹配在排除型字符类内部命名的 Unicode 属性 (≡ \P{Name})

Perl 字符组(仅限所有 ASCII 码)Permalink

Perl character classes (all ASCII-only) \d 数字 (≡ [0-9]) \D 非数字 (≡ [^0-9]) \s 白空格 (≡ [\t\n\f\r ]) \S 非白空格 (≡ [^\t\n\f\r ]) \w 整个单词 (≡ [0-9A-Za-z_]) \W 非整个单词 (≡ [^0-9A-Za-z_]) \h 水平空格 (不支持) \H 非水平空格 (不支持) \v 垂直空格 (不支持) \V 非垂直空格 (不支持)

ASCII 字符类Permalink

ASCII character classes [[:alnum:]] 字母和数字 (≡ [0-9A-Za-z])   [[:alpha:]] 字母 (≡ [A-Za-z])   [[:ascii:]] ASCII字符 (≡ [\x00-\x7F])   [[:blank:]] 空白字符 (≡ [\t ])   [[:cntrl:]] 控制字符 (≡ [\x00-\x1F\x7F])   [[:digit:]] 数字 (≡ [0-9])   [[:graph:]] 图形字符,可打印字符,可见字符 (≡ [!-~][A-Za-z0-9!"#$%&'()*+,\-./:;<=>?@[\\\]^_````{ }~]`) [[:lower:]] 小写字符 (≡ [a-z])   [[:print:]] 可打印字符 (≡ [ -~][ [:graph:]])   [[:punct:]] 标点字符 (≡ [!-/:-@[-````{-~]`)   [[:space:]] 白空格 (≡ [\t\n\v\f\r ])   [[:upper:]] 大些字符 (≡ [A-Z])   [[:word:]] 整个单词 (≡ [0-9A-Za-z_])   [[:xdigit:]] 十六进制字符 (≡ [0-9A-Fa-f])  

Unicode 字符类名称 - 常规类别Permalink

Unicode character class names–general category C 其它 Cc control Cf format Cn 未赋值码点 (NOT SUPPORTED) Co 私有用途 Cs 代理项 surrogate L 字母 LC 大小写字母(不支持) L& 大小写字母(不支持) Ll 小写字母 Lm 修饰字母 Lo 其他字母 Lt 首字母大写 Lu 大写字母 M 标记 mark Mc 间距标记 spacing mark Me 封闭标记 enclosing mark Mn 非间距标记 non-spacing mark N 数字 number Nd 十进制数字 decimal number Nl 字母或数字 letter number No 其它数字 other number P 标点符号 punctuation Pc 连接符 connector punctuation Pd 短划线 dash punctuation Pe 结束标点 close punctuation Pf 后引号 final punctuation Pi 前引号 initial punctuation Po 其它标点符号 other punctuation Ps 开始标点 open punctuation S 符号 symbol Sc 货币符号 currency symbol Sk 修饰符符号 modifier symbol Sm 数学符号 math symbol So 其它符号 other symbol Z 分隔符 separator Zl 行分隔符 line separator Zp 段落分隔符 paragraph separator Zs 空白分隔符 space separator

Unicode 字符类名称 - 文字系统Permalink

Unicode character class names–scripts 阿德拉姆Adlam 阿霍姆语Ahom 安纳托利亚 _ 象形文字Anatolian_Hieroglyphs 阿拉伯语Arabic 亚美尼亚语Armenian 阿维斯陀语Avestan 巴厘文Balinese 巴姆穆文Bamum Bassa_Vah 巴塔克文Batak 孟加拉语Bengali 拜克舒克文Bhaiksuki 汉语拼音字母Bopomofo 婆罗米文Brahmi 布莱叶盲文Braille 布吉文Buginese 布锡语Buhid 加拿大 _ 澳大利亚土著语Canadian_Aboriginal 卡里亚文Carian 高加索 _ 阿尔巴尼亚语Caucasian_Albanian 占文Chakma Cham 切罗基语Cherokee 花剌子模语Chorasmian 通用Common 科普特语Coptic 楔形文字Cuneiform 塞浦路斯语Cypriot Cypro_Minoan 西里尔字母Cyrillic 德塞莱特文Deseret 梵文Devanagari Dives_Akuru 多格兰语Dogra 杜普洛伊速记体Duployan 埃及 _ 象形文字Egyptian_Hieroglyphs 爱尔巴桑语Elbasan 埃利迈语Elymaic 埃塞俄比亚文Ethiopic 格鲁吉亚语Georgian 格拉哥里语Glagolitic 哥特语Gothic 格兰塔字母Grantha 希腊语Greek 古吉拉特语Gujarati Gunjala_Gondi 锡克教文Gurmukhi 汉语Han 韩语Hangul Hanifi_Rohingya 汉奴劳族文Hanunoo 哈特兰文Hatran 希伯来语Hebrew 日文Hiragana 英制文字 _ 阿拉姆语Imperial_Aramaic 继承Inherited 碑文 _ 巴拉维语Inscriptional_Pahlavi 碑文 _ 帕提亚语Inscriptional_Parthian 爪哇文Javanese 凯提文Kaithi 埃纳德语Kannada 片假名Katakana 克耶 _ 列支敦士登Kayah_Li 卡罗须提文Kharoshthi 契丹 _小_文字Khitan_Small_Script 高棉语Khmer 克吉奇文Khojki 信德文Khudawadi 老挝语Lao 拉丁语Latin 雷布查文Lepcha 林布文Limbu 线性 _ALinear_A 线性 _BLinear_B 僳文傈Lisu 利西亚文Lycian 吕底亚文Lydian 马哈詹语Mahajani 望加锡语Makasar 马拉雅拉姆语Malayalam 阿拉米文Mandaic 摩尼文Manichaean Marchen Masaram_Gondi 梅德法伊德林文Medefaidrin 梅泰族 _ 曼尼普尔文Meetei_Mayek 门德 _ 门迪文Mende_Kikakui 麦罗埃 _ 手写体Meroitic_Cursive 麦罗埃 _ 象形文字Meroitic_Hieroglyphs 苗文Miao 莫迪文Modi 蒙古语Mongolian 毛里塔尼亚乌吉亚Mro 穆尔塔尼Multani 缅甸Myanmar 纳巴泰Nabataean 楠迪梵文Nandinagari New_Tai_Lue Newa Nko 女书Nushu Nyiakeng_Puachue_Hmong 欧甘字母Ogham Ol_Chiki 古语 _ 匈牙利语Old_Hungarian 古语 _ 意大利语Old_Italic 古语 _ 北部 _ 阿拉伯语Old_North_Arabian 古语 _ 彼尔姆语Old_Permic 古语 _ 波斯语Old_Persian 古语 _ 古索格代亚纳语Old_Sogdian 古语 _ 南部 _ 阿拉伯语Old_South_Arabian 古语 _ 突厥语Old_Turkic Old_Uyghur 奥里雅语Oriya 欧塞奇语Osage 奥斯曼亚字母Osmanya 救世苗文 _ 苗语Pahawh_Hmong 帕米拉语Palmyrene Pau_Cin_Hau Phags_Pa 腓尼基语Phoenician Psalter_Pahlavi 勒姜语Rejang 古北欧文字Runic 撒马利亚文Samaritan 索拉什特拉文Saurashtra 夏拉达文Sharada 萧伯纳文Shavian 悉昙文字Siddham 手语书写体SignWriting 僧伽罗语Sinhala 粟特语Sogdian Sora_Sompeng 索永布语Soyombo 巽他语Sundanese Syloti_Nagri 叙利亚语Syriac 他加禄语Tagalog 塔班瓦语Tagbanwa Tai_Le Tai_Tham Tai_Viet 泰克里文Takri 泰米尔语Tamil 西夏语Tangsa Tangut 泰卢固语Telugu 它拿字母Thaana 泰语Thai 藏语Tibetan 提夫纳语Tifinagh Tirhuta Toto 乌加里特语Ugaritic 瓦依语Vai Vithkuqi 万秋文Wancho Warang_Citi 雅兹迪语Yezidi 彝语Yi Zanabazar_Square

Vim 字符类Permalink

Vim character classes \i 匹配标识符字符(不支持) VIM \I \i 不包括数字字符(不支持)VIM \k 匹配关键字字符(不支持)VIM \K \k 不包括数字字符(不支持)VIM \f 匹配文件名称字符(不支持)VIM \F \f 不包括数字字符(不支持)VIM \p 匹配可打印字符(不支持)VIM \P \p 不包括数字字符(不支持)VIM \s 匹配空白字符 (≡ [ \t]) (NOT SUPPORTED) VIM \S 匹配非空白字符 (≡ [^ \t]) (NOT SUPPORTED) VIM \d 数字 (≡ [0-9]) VIM \D\d VIM \x 十六进制数字 (≡ [0-9A-Fa-f]) (NOT SUPPORTED) VIM \X\x (NOT SUPPORTED) VIM \o 八进制数字 (≡ [0-7]) (NOT SUPPORTED) VIM \O\o (NOT SUPPORTED) VIM \w 单词 VIM \W\w VIM \h 匹配单词起始字符 (NOT SUPPORTED) VIM \H\h (NOT SUPPORTED) VIM \a 匹配字母字符 (NOT SUPPORTED) VIM \A\a (NOT SUPPORTED) VIM \l 小写字符 (NOT SUPPORTED) VIM \L 非小写字符 (NOT SUPPORTED) VIM \u 大写字符 (NOT SUPPORTED) VIM \U 非大写字符 (NOT SUPPORTED) VIM \_x \x 加上换行符,匹配任意 x (NOT SUPPORTED) VIM \c 忽略大小写 (NOT SUPPORTED) VIM \C 匹配大小写 (NOT SUPPORTED) VIM \m magic (NOT SUPPORTED) VIM \M nomagic (NOT SUPPORTED) VIM \v verymagic (NOT SUPPORTED) VIM \V verynomagic (NOT SUPPORTED) VIM \Z 忽略 Unicode 组合字符的不同 (NOT SUPPORTED) VIM

MagicPermalink

Magic (?{code}) PERL 中的任意 Perl 代码(不支持) (??{code}) PERL 中延迟的任意 Perl 代码(不支持) (?n) 递归调用 regexp 捕获组 n (不支持) (?+n) 递归调用相对组 +n (不支持) (?-n) 递归调用相对组 -n (不支持) (?C) PCRE 回调(不支持) PCRE (?R) 递归调用整个 regexp (等价于 (?0))(不支持) (?&name) 递归调用已命名组(不支持) (?P=name) 匹配已命名反向引用(不支持) (?P>name) 递归调用已命名组(不支持) (?(cond)true|false) 条件分支(不支持) (?(cond)true) 条件分支(不支持) (*ACCEPT) 让 regexps 更类似于 Prolog (不支持) (*COMMIT) (NOT SUPPORTED) (*F) (NOT SUPPORTED) (*FAIL) (NOT SUPPORTED) (*MARK) (NOT SUPPORTED) (*PRUNE) (NOT SUPPORTED) (*SKIP) (NOT SUPPORTED) (*THEN) (NOT SUPPORTED) (*ANY) 设置换行约定(不支持) (*ANYCRLF) (NOT SUPPORTED) (*CR) (NOT SUPPORTED) (*CRLF) (NOT SUPPORTED) (*LF) (NOT SUPPORTED) (*BSR_ANYCRLF) 设置 \R 约定(不支持) PCRE (*BSR_UNICODE) (NOT SUPPORTED) PCRE

后记Permalink

本文主要目的是回顾和整理一个 cheatsheet。很显然,一篇文章是不可能教会你正则式的,所以本文也不怎么给示例,要想讲清楚会需要太多示例。

作为一个示例,cmdr 包含一个工具函数 UnescapeUnicode,其源码为:

// UnescapeUnicode 解码 \uxxxx 为 unicode 字符; 但是输入的 b 应该是 yaml 格式
func UnescapeUnicode(b []byte) string {
	b = reFind.ReplaceAllFunc(b, expandUnicodeInYamlLine)
	return string(b)
}

func expandUnicodeInYamlLine(line []byte) []byte {
	// TODO: restrict this to the quoted string value
	return reFindU.ReplaceAllFunc(line, expandUnicodeRune)
}

func expandUnicodeRune(esc []byte) []byte {
	ri, _ := strconv.ParseInt(string(esc[2:]), 16, 32)
	r := rune(ri)
	repr := make([]byte, utf8.RuneLen(r))
	utf8.EncodeRune(repr, r)
	return repr
}

var reFind = regexp.MustCompile(`[^\s\:]+\:\s*["']?.*\\u.*["']?`)

jex.im 为这个 Pattern 提供了一个可视化图解:

ReferencesPermalink

标签: golang regexp

分类: golang regexp

更新时间: December 3, 2021

 许可信息:  本文采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可,转载请注明 hedzr 或出处链接。

向前 向后


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK