logo BT编程语言
首页动态文档关于登录更新记录
BT编程语言文档

Regex正则表达式

Regex:是正则表达式(regular expression)的简写。 ‌‌正则表达式(Regular Expression)‌是一种强大的文本处理工具,用于匹配字符串中的特定模式。它由普通字符和特殊字符(称为元字符)组成,用于描述一种字符串匹配的模式。正则表达式可以检查一个字符串是否含有某种子串、将匹配的子串做替换或从某个字符串中取出符合某个条件的子串等。‌ 正则表达式在许多编程语言和文本编辑器中都有广泛应用,例如VsCode、SublimeText等工具,以及PHP、Perl、‌Java、‌JavaScript、‌C#等编程语言。它主要用于文本搜索、替换、模式匹配等操作,能够帮助程序员高效地处理和分析文本数据。 例如:一个简单的正则表达式^\d+$用于匹配一串数字,其中^表示字符串的开始,\d+表示一个或多个数字。

语法

正则表达式主要由两个斜杠组成,最后一个斜杠后面为修饰符,用于配置匹配模式,如下:

re = /pattern/modifiers

pattern(模式) 表达式的模式 modifiers(修饰符) 用于指定全局匹配、区分大小写的匹配和多行匹配

修饰符

修饰符用于执行区分大小写和全局匹配:
  • i 执行对大小写不敏感的匹配
  • g 执行全局匹配(查找所有匹配而非在找到第一个匹配后停止)
  • m 执行多行匹配
  • s 允许 . 匹配 \n

字符类

字符类允许你定义匹配一组字符的规则,支持以下几种模式:
  • [xyz] 匹配 x、y 或 z 中的任意一个字符(并集)
  • [^xyz] 匹配除 x、y 和 z 之外的任何字符(取反)
  • [0-9] 匹配 0 到 9 范围内的数字(区间匹配)
  • [a-z] 匹配 a 到 z 范围内的任何小写字母(区间匹配)
  • [A-Z] 匹配 A 到 Z 范围内的任何大写字母(区间匹配)
  • [A-z] 匹配 A 到 z 范围内的任何大写和小写字母(区间匹配)
  • [[:alpha:]] 匹配任意字母字符(ASCII 字符类,等价于 [A-Za-z])
  • [[:^alpha:]] 匹配任何非字母字符(取反的 ASCII 字符类,等价于 [^A-Za-z])
  • [x[^xyz]] 嵌套/分组字符类,匹配 x 和除 y 和 z 之外的任意字符
  • [a-y&&xyz] 交集操作,匹配 x 或 y(即 a-y 与 xyz 的交集)
  • [0-9&&[^4]] 使用交集和取反进行的减法操作,匹配 0-9 中除 4 之外的字符
  • [0-9--4] 直接减法操作,匹配 0-9 中除 4 之外的字符
  • [a-g~~b-h] 对称差操作,匹配 a 和 h(即 a-g 与 b-h 的对称差)
  • [\[\]] 在字符类中转义,匹配 [ 或 ]
  • [a&&b] 空字符类,匹配不到任何字符

元字符

元字符(Metacharacter)是拥有特殊含义的字符:
  • . 匹配任意字符,除了换行符(如果设置了 s 标志,. 也可以匹配换行符)
  • \d 匹配任意数字字符(等价于 Unicode 类 \p{Nd})
  • \D 匹配任意非数字字符
  • \s 匹配任意空白字符(包括空格、制表符等)
  • \S 匹配任意非空白字符
  • \w 匹配任意单词字符(包括字母、数字和下划线)
  • \W 匹配任意非单词字符
  • \* 匹配字面上的 *,适用于所有 ASCII 字符,除了 [0-9A-Za-z<>]
  • \a 响铃符(\x07)
  • \f 换页符(\x0C)
  • \t 水平制表符(tab 键)
  • \n 换行符
  • \r 回车符
  • \v 垂直制表符(\x0B)
  • \A 匹配输入的开头
  • \z 匹配输入的结尾
  • \b 单词边界断言
  • \B 非单词边界断言(即反向的单词边界)
  • \b{start}, \< 单词开始边界断言
  • \b{end}, \> 单词结束边界断言
  • \b{start-half} 单词开始边界的半边断言
  • \b{end-half} 单词结束边界的半边断言
  • \123 八进制字符代码,最多三位数(当启用时)
  • \x7F 十六进制字符代码(精确为两位)
  • \x{10FFFF} 任何对应于 Unicode 代码点的十六进制字符代码
  • \u007F 十六进制字符代码(精确为四位)
  • \u{7F} 任何对应于 Unicode 代码点的十六进制字符代码
  • \U0000007F 十六进制字符代码(精确为八位)
  • \U{7F} 任何对应于 Unicode 代码点的十六进制字符代码
  • \p{Letter} Unicode 字符类(例如,匹配任意字母字符)
  • \P{Letter} 反向的 Unicode 字符类(例如,匹配任何非字母字符)
  • \pX 匹配由一个字母标识的 Unicode 字符类,例如 \pL 匹配所有字母
  • \PX 匹配由一个字母标识的取反 Unicode 字符类,例如 \PL 匹配非字母字符

重复匹配

在BT的正则表达式中,可以使用以下语法来指定重复模式:
  • x* 匹配零次或多次 x(贪婪匹配)
  • x+ 匹配一次或多次 x(贪婪匹配)
  • x? 匹配零次或一次 x(贪婪匹配)
  • x*? 匹配零次或多次 x(非贪婪/懒惰匹配)
  • x+? 匹配一次或多次 x(非贪婪/懒惰匹配)
  • x?? 匹配零次或一次 x(非贪婪/懒惰匹配)
  • x{n,m} 匹配至少 n 次 x,且至多 m 次 x(贪婪匹配)
  • x{n,} 匹配至少 n 次 x(贪婪匹配)
  • x{n} 精确匹配 n 次 x
  • x{n,m}? 匹配至少 n 次 x,且至多 m 次 x(非贪婪/懒惰匹配)
  • x{n,}? 匹配至少 n 次 x(非贪婪/懒惰匹配)
  • x{n}? 精确匹配 n 次 x(非贪婪/懒惰匹配)

提示:在这里,贪婪匹配 意味着正则表达式会尽可能多地匹配,而 非贪婪/懒惰匹配 则会尽可能少地匹配

空匹配

以下是BT正则表达式中与空匹配相关的符号及其含义:
  • ^ 匹配输入的开头(或在多行模式下匹配行的开头)
  • $ 匹配输入的结尾(或在多行模式下匹配行的结尾)
  • \A 仅匹配输入的开头(即使启用了多行模式也只匹配整个文本的开头)
  • \z 仅匹配输入的结尾(即使启用了多行模式也只匹配整个文本的结尾)
  • \b 匹配 Unicode 单词边界(当一侧是单词字符 \w,另一侧是非单词字符 \W、\A 或 \z 时)
  • \B 匹配非 Unicode 单词边界
  • \b{start}, \< 匹配 Unicode 单词开头边界(左侧为 \W 或 \A,右侧为 \w)
  • \b{end}, \> 匹配 Unicode 单词结尾边界(左侧为 \w,右侧为 \W 或 \z)
  • \b{start-half} 匹配半个 Unicode 单词开头边界(左侧为 \W 或 \A)
  • \b{end-half} 匹配半个 Unicode 单词结尾边界(右侧为 \W 或 \z)

提示:这些符号常用于匹配位置或边界,而不是实际字符

分组与标志

在BT正则表达式中,可以使用以下语法来进行分组:
  • (exp) 编号捕获组,捕获的内容会根据左括号的顺序进行编号(从 1 开始)。
  • (?Pexp)(?exp) 命名捕获组,同时也会被编号。组名必须是字母数字(a-z, A-Z, 0-9)。
  • (?:exp) 非捕获组,这种组只进行匹配但不会捕获结果。
  • (?flags) 在当前分组中设置标志(影响该分组内的匹配方式)。
  • (?flags:exp) 为特定的表达式 exp 设置标志,且该表达式为非捕获组。

ASCII 字符类

以下是基于 UTS#18 提供定义的 ASCII 字符类及其含义:
  • [[:alnum:]] 字母数字字符(即 [0-9A-Za-z])。
  • [[:alpha:]] 字母字符(即 [A-Za-z])。
  • [[:ascii:]] ASCII 字符(即 [\x00-\x7F],包括从 0 到 127 的所有 ASCII 字符)。
  • [[:blank:]] 空白字符(即 [\t ],包括水平制表符和空格)。
  • [[:cntrl:]] 控制字符(即 [\x00-\x1F\x7F],包括不可打印的控制字符)。
  • [[:digit:]] 数字字符(即 [0-9])。
  • [[:graph:]] 可见的图形字符(即 [!-~],包括除空格外的所有可打印字符)。
  • [[:lower:]] 小写字母(即 [a-z])。
  • [[:print:]] 可打印字符(即 [ -~],包括空格和所有可见的图形字符)。
  • [[:punct:]] 标点符号(即 [!-/:-@\[-{-~]`,包括标点和符号)。
  • [[:space:]] 空白字符(即 [\t\n\v\f\r ],包括制表符、换行符、垂直制表符、换页符、回车符和空格)。
  • [[:upper:]] 大写字母(即 [A-Z])。
  • [[:word:]] 单词字符(即 [0-9A-Za-z_],包括字母、数字和下划线)。

Unicode支持

Unicode 对内存使用和搜索速度的影响

该正则表达式库默认启用了对 Unicode 的全面支持,在大多数情况下,支持Unicode所需的额外内存开销是可以忽略的,并且通常不会影响搜索速度,但在某些情况下可能会有影响。

关于内存使用:

Unicode 的影响主要体现在 Unicode 字符类的使用上。Unicode 字符类往往非常庞大。例如,默认的 \w 匹配大约 14 万个不同的代码点。这需要额外的内存,并可能使正则表达式的编译变慢。虽然偶尔使用 \w 影响不大,但如果你写了 \w{100},那么默认情况下将生成一个相当大的正则表达式。 例如,(?-u:\w) 的 ASCII 版本明显比 Unicode 版本小得多,所以如果你的需求可以通过 ASCII 满足,最好使用 ASCII 字符类。ASCII 版本的 \w 可以通过多种方式表示,以下都是等价的:
  • [0-9A-Za-z_]
  • (?-u:\w)
  • [[:word:]]
  • [\w&&\p{ascii}]

关于搜索速度:

即使使用大型 Unicode 字符类,搜索速度通常也能很好地处理 Unicode。不过,一些更快的内部正则表达式引擎无法处理支持 Unicode 的单词边界断言。因此,如果你不需要 Unicode 感知的单词边界断言,建议使用 (?-u:\b) 代替 \b,前者使用 ASCII 版本的单词字符定义。 总之,虽然启用 Unicode 支持通常不会显著影响内存和性能,但在某些情况下使用 ASCII 类可以减少开销并提升性能。 BT语言的正则完全实现了 Unicode 技术标准 #18(UTS#18)中规定的“基本 Unicode 支持”(第一级)。 字符类 \w、\d 和 \s 默认都是支持 Unicode 的。使用 (?-u:\w) (?-u:\d)(?-u:\s) 可获得仅支持 ASCII 的定义。 类似的 \b 和 \B 使用 Unicode 定义的“单词”字符。若要获得仅支持 ASCII 的单词边界,可使用(?-u:\b)(?-u:\B)。这同样适用于特殊的单词边界断言(即 \b{start}\b{end}\b{start-half}\b{end-half})。 在多行模式下,^ 和 $ 不支持 Unicode,也就是说,它们只识别 \n(假设未启用 CRLF 模式),而不会识别 Unicode 定义的其他行终止符形式。 大小写不敏感的搜索支持 Unicode 并使用简单的大小写折叠。 Unicode 的一般类别、脚本和许多布尔属性默认可通过 \p{property name} 语法使用。 在所有情况下,匹配的结果都使用字节偏移量报告,准确地说,是 UTF-8 编码单元的偏移量。这允许在常数时间内对文本进行索引和切片操作。 在BT中,默认情况下,正则匹配是 Unicode 感知的,这意味着它可能匹配的比你想象的要多。例如:\d 要仅匹配 ASCII 十进制数字,以下所有内容都是等效的:
  • [0-9]
  • (?-u:\d)
  • [[:digit:]]
  • [\d&&\p{ascii}]