正则表达式是一个包含搜索模式的字符串,用于匹配其他的字符串。Tcl正则表达式是基于1003.2规范和一些Perl5扩展。Tcl正则表达式是包含一个或多个约束或量化原子连接而成。正则表达式由POSIX定义,有两种风格:扩展正则(ERE)和基本正则(BRE)。ERE与传统的egrep大致相同,BRE与传统的ed大致相同。Tcl实现另一种风格:高级正则(ARE),在ERE的基础上添加一些重要的扩展。
BRE与ERE在几个方面有所不同。
1.在BRE中字符“|”、“+”和“?”只是普通字符,没有与它们的功能等价的字符。
2.边界的分隔符是“\{”和“\}”,“{”和“}”本身为普通的字符。
3.嵌套子表达式的括号是“\(”和“\)”,“(”和“)”本身为普通字符。
4.除了在正则表达式或圆括号子表达式的开头以外,“^”均为普通字符。除了在正则表达式或圆括号子表达式的末尾以外,“$”均为普通字符。
5.如果“*”出现在正则表达式或圆括号子表达式的开头(或者有一个前导字符^),则为普通字符。
6.只能使用个位数的反向引用。
7.“\<”和“\>”等价于“[[:<:]]”和“[[:>:]]”。
8.除以上转义外,没有其他任何转义。
量化修饰符
使用{}的修饰符,其中m和n是无符号十进制整数,允许发范围是[0,255]。
符号 | 说明 |
* | 匹配0或多个原子 |
+ | 匹配1或多个原子 |
? | 匹配0或1个原子 |
{m} | 匹配m个原子 |
{m,} | 匹配至少m个原子 |
{m,n} | 匹配m到n个原子 |
*? +? ?? {m}? {m,}? {m,n}? | 非贪婪性量词,如果匹配具有相同的优先级,会进行最小的匹配而不是最大的匹配。 |
原子
原子是Tcl正则表达式中相对独立的部分,re代表任何正则表达式。
原子 | 说明 |
(re) | 匹配re,并捕获。 |
(?:re) | 匹配re。 |
() | 匹配空字符串,并捕获。 |
(?:) | 匹配空字符串。 |
[chars] | 括号表达式,匹配其中的任意一个字符。 |
. | 匹配任意单个字符。 |
\k | 匹配非字母字符k做为普通字符。 |
\c | 仅ARE,转义,见下方转义中字符条目转义\cX。 |
{ | 当后面跟一个数字以外的字符时,匹配左大括号,如果跟着一个数字,则为量化修饰符的边界。 |
x | 如果x是一个没有其他意义的单个字符,则匹配该字符。 |
约束
当约束满足特定条件时,匹配空字符串。约束后面不能有量化修饰符。在特定条件下约束匹配空字符串,re代表任何不以“\”结尾的正则表达式。
约束 | 说明 |
^ | 匹配行开头 |
$ | 匹配行结尾 |
(?=re) | 仅ARE,从匹配re的字符串开始正向查找。re中的括号是不可捕获的。 |
(?!re) | 仅ARE,从不匹配re的字符串开始正向查找。re中的括号是不可捕获的。 |
括号表达式
括号表达式是包含在“[]”中的字符列表。通常匹配列表中的任何单个字符。如果以“^”开头,则匹配不在列表中的字符。如果列表中的两个字符用“-”分隔,表示两个字符及其之间的全部字符。Tcl中的范围总是使用Unicode排序序列,但是其他程序可能使用其他排序序列,这可能是程序之间不兼容的原因之一。
字符分类
在括号表达式中,字符分类用“[:”和“:]”包围起来,表示所有属于该分类的字符。字符分类不能做为范围的端点。支持的字符分类如下:
类别 | 说明 | 类别 | 说明 | 类别 | 说明 |
alpha | 字母 | upper | 大写字母 | lower | 小写字母 |
digit | 十进制数字 | xdigit | 十六进制数字 | alnum | 字母或数字 |
可打印字符,包括空格 | blank | 空格或制表符 | space | 在显示文本中产生空白的字符 | |
punct | 标点字符 | graph | 可见字符,不包括空格 | cntrl | 控制字符 |
约束
仅ARE,括号表达式有两种特殊情况,表示一种约束:“[[:<:]]”和“[[:>:]]”,分别匹配单词开头和结尾的空字符串。单词的定义为前后都没有单词字符的序列。而单词字符是指字母和数字以及连字符“_”。
转义
仅ARE,以“\”开头,后面跟着字母、数字。转义有几种类型:字符条目、分类简写、约束转义以及反向引用。
字符条目
字符 | 说明 | 字符 | 说明 | 字符 | 说明 | 字符 | 说明 |
\a | 警告字符 | \b | 回退字符 | \B | 反斜杠 | \cX | 只保留字符X的低五位,其他位为0 |
\e | esc字符,也就是八进制033 | \f | 换页符 | \n | 换行符 | \r | 回车符 |
\t | 水平制表符 | \uwxyz | unicode字符wxyz为 十六进制数字 | \ustuvwxyz | stuvwxyz为十六进制数字 | \v | 垂直制表符 |
\xhh | 十六进制为0xhh的字符 | \0 | 字符0 | \xyz | 八进制为0xyz的字符,x范围为0-3,否则认为只有两位 | \xy | 八进制为0xy的字符 |
分类简写
字符 | 说明 | 字符 | 说明 |
\d | [[:digit:]],十进制数字。 | \D | [^[:digit:]],非十进制数字。 |
\s | [[:space:]],文本中的空白符。 | \S | [^[:space:]],文本中的非空白符。 |
\w | [[:alnum:]_],字母数字下划线。 | \W | [^[:alnum:]_],除字母数字下划线的字符。 |
约束转义
字符 | 说明 | 字符 | 说明 |
\A | 匹配字符串的开头 | \Z | 匹配字符串的结尾 |
\m | 匹配单词的开头 | \M | 匹配单词的结尾 |
\y | 匹配单词的开头或结尾 | \Y | 匹配非单词的开头或结尾 |
反向引用
反向引用匹配由数字指定的可捕获号表达式匹配的相同的字符串。子表达式必须在反向引用之前,按括号的顺序编号。非捕获括号不进行计算。由于八进制转义与反向引用转义可能存在歧义,所以前导零总是表示八进制转义,一个单独的非零数字表示反向引用。如果在适当(数字在反向引用范围内)的可捕获表达式之后出现非零开头的多位数字,则将其视为反向引用,否则表示八进制转义。
字符 | 说明 |
\m | 反向引用,m为非零整数 |
\mnn | 反向引用,m为非零整数,nn为任意整数。mnn不大于捕获的括号的数量 |
元语法
通常,正则表达式使用的风格是由应用程序的方法指定的。如果任何风格的表达式以“***:”开头,则剩余的表达式为ARE。如果任何风格的表达式以“***=”开头,则其余的表达式被认为是一个文字字符串,将所有字符视为普通字符。如果应用程序将输入的字符串视为文本字符或者字符串以“***=”开头,则以下的嵌入式选项和注释都不可使用。
嵌入式选项
ARE表达式可能会以嵌入式选项开头,嵌入式选项会影响其后的正则表达式re,嵌入式选项只能出现在表达式之前,嵌入式选项的格式如下:
(?xyz)
xyz为一或多个选项字母,可用的选项字母如下:
选项 | 说明 | 选项 | 说明 |
b | 其余的表达式是一个BRE | p | 部分行敏感匹配,只有“.”和方括号表达式是行敏感的。 |
c | 匹配时区分大小写 | q | 剩余的re为文本字符串。 |
e | 其余的表达式是一个ERE | s | 非行敏感匹配,默认选项。 |
i | 匹配时忽略大小写 | t | 使用严格语法,默认选项。 |
m | 等价于n | w | 非部分行敏感匹配,与p选项正好相反,只有“^”和“$”是行敏感的。 |
n | 行敏感匹配,“.”与使用^的方括号表达式不会匹配换行符。“^”与“$”分别匹配行开头和行结尾。 | x | 使用扩展语法,空白字符(空白、制表符、换行符以及任何属于空格字符类的字符)会被忽略,在“#”和下一个换行符或re结尾之间的字符会被忽略,允许分段和注释复杂的正则表达式。扩展语法有三个例外: 1.“\”之后的空白字符和“#”会被保留。 2.括号表达式中的空白字符和“#”会被保留。 3.在多字符符号中空白字符和“#”是非法的,如ARE中的“(?:”或者BRE中的“\(” |
注释
正则表达式语法除了常见的严格语法,还可以通过-expanded开关或者ARE中指定嵌入式选项x来开启另一种语法,扩展语法。在使用扩展语法时,对于复杂的正则表达式可以进行注释。注释的格式如下:
(?#ttt)
其中ttt为任意不包含“)”的文本,会被完全忽略。在方括号以及多字符符号(如ARE中的“(?:”)中不可以有注释。