1、前言
API中对于正则表达式的注释是:
正则表达式的规范和语义与JavaScript相同
详细的规范可以参考:http://ecma-international.org/ecma-262/5.1/#sec-15.1
打开链接,全英文的、、、瞄了一下
不明觉厉!!!
然后,花了一段时间对其支持的特性进行了测试
在附表中将Dart中正则表达式的特性列出来,简单明了
以供大家参考
2、点号通配符
关于Dart中正则表达式支持的特性
越是深入了解,越是感觉复杂
附表中的内容可能不全,但基本上都有提及
这里需要注意其中的 . 点号通配符
通常,点号是不能匹配换行符的
这也使得 .* 表达式变得有些古怪
由于最初Unix正则表达式都是逐行处理的
所以可能后来新的语法是为了保证一致性吧!
但是在测试的时候,结果让人有点头大
例如,处理字符串 ABC\nDEF
import 'dart:io';
void main() { String str = "ABC\nDEF"; RegExp reg = new RegExp(r".*"); Iterable<Match> matches = reg.allMatches(str); for (Match m in matches) { print("${m.group(0).isEmpty ? "Match is Empty\nIndex is ${m.end}" : "Match is ${m.group(0)} \nAscii is ${m.group(0).codeUnits}\nIndex is ${m.end}"}"); print("--end--\n"); } }
运行结果:
Match is ABC
Ascii is [65, 66, 67]
Index is 3
--end--
Match is Empty
Index is 3
--end--
Match is DEF
Ascii is [68, 69, 70] Index is 7 --end-- Match is Empty Index is 7 --end--
通过分析,对于正则表达式 .*
共匹配有4个Match
分别是:ABC 空 DEF 空
匹配到字符串的 \n 的时候结束
这里 \n 并没有被捕获,而是捕获位置
是不是有点像 $
那么我们来匹配一下 .*$
运行结果:
Match is DEF
Ascii is [68, 69, 70]
Index is 7
--end--
Match is Empty
Index is 7
--end--
什么意思呢?
在匹配 .* 的时候,如果遇到 \n
处理方式和遇到 $ 一样,停止“本行”匹配
但是不捕获文本、、、有点绕
如果我们打开RegExp的multiLine开关,结果会怎么样?
大家可以动手测试一下
new RegExp(".*", multiLine:true);
对于 .* 表达式,结果没有任何变化
但是对于 .*$ ,结果此时和 .* 的结果一样
也就是说,在打开multiLine开关的时候
如果表达式 .* 遇到 \n ,处理方式和遇到 $ 一样
同时匹配之前的字符串、、、
如果我们想捕获 \n 这个字符串的话,有办法吗?
在测试过后,得出结论
无论是否打开multiLine, .* 都不会匹配 \n 本身
但是,无论是否打开multiLine
[] 字符组和 [^] 排除型字符组都会匹配 \n 本身
可以试一下匹配 [^!]* ,运行结果如下:
Match is ABC
DEF
Ascii is [65, 66, 67, 10, 68, 69, 70]
Index is 7
--end--
Match is Empty
Index is 7
--end--
\n 的Ascii码是10,结果没有问题
\n 作为文本被捕获,字符串结束的位置也被捕获
如果说的不够清楚,大家可以打开、关闭multiLine开关的情况下
分别测试如下表达式: ^.* 、 .*$ 、 ^.*$ ,然后体会一番
点号通配模式,也有个称呼叫单行模式
在匹配多行文本的时候,需要特别注意
对最终结果还是影响很大的、、、
3、附表:Dart中正则表达式支持的特性
特性
|
描述
|
\
|
将下一个字符标记为一个特殊字符、或一个原义字符、或一个后向引用、或一个八进制转义符。例如,”n”匹配字符”n”。”\n”匹配一个换行符。序列”\\”匹配”\”,”\(“则匹配”(“。 |
.
|
匹配任何单个字符。 |
^
|
匹配输入字符串的开始位置。如果设置了RegExp 对象的Multiline属性,^也匹配”\n”或”\r”之后的位置。例如,”^.”可以匹配”abc\n123″中的”a”和”1″。 |
$
|
匹配输入字符串的结束位置。如果设置了RegExp对象的Multiline属性,$也匹配 “\n” 或”\r”之前的位置。例如,”.$”可以匹配”abc\n123″中的”c”和”3″。 |
*
|
匹配前面的子表达式零次或多次。例如,”zo*”能匹配 “z”或”zoo”整个字符串。”*”等价于{0,}。 |
+
|
匹配前面的子表达式一次或多次。例如,”zo+” 能匹配 “zo” 以及 “zoo”,但不能匹配 “z”。”+”等价于{1,}。 |
? (限制符)
|
匹配前面的子表达式零次或一次。例如,”do(es)?” 可以匹配 “do” 或 “does”整个字符串。”?”等价于 {0,1}。 |
?(非贪婪模式)
|
当该字符紧跟在任何一个其他限制符 (*, +, ?, {n}, {n,}, {n,m}) 后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串”oooo”,”o+?”将匹配单个”o”,而”o+”将匹配”oooo”。 |
x|y
|
匹配x或y。例如,”z|food”能匹配”z”或”food”。”(z|f)ood” 则匹配”zood”或”food”。 |
[xyz]
|
字符集合。匹配所包含的任意一个字符。例如,”[abc]” 可以匹配”plain”中的”a”。Dart中不支持字符组嵌套,如:[[a-z]&&[^b]]。 |
[^xyz]
|
排除字符集合。匹配未包含的任意字符。例如, “[^abc]” 可以匹配 “plain” 中的”p”。 |
[a-z]
|
字符范围。匹配指定范围内的任意字符。例如,”[a-z]”可以匹配”a”到”z”范围内的任意小写字母字符。 |
[^a-z]
|
排除字符范围。匹配任何不在指定范围内的任意字符。例如,”[^a-z]”可以匹配任何不在”a”到”z”范围内的任意字符。 |
{n}
|
n 是一个非负整数。匹配确定的n次。例如,”o{2}”不能匹配”Bob”中的”o”,但是能匹配”food”中的”oo”。 |
{n,}
|
n 是一个非负整数。至少匹配n 次。例如,”o{2,}”不能匹配”Bob”中的”o”,但能匹配”fooood”中的”oooo”。”o{1,}”等价于”o+”。”o{0,}”则等价于”o*”。 |
{n,m}
|
m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。刘, “o{1,3}” 将匹配 “fooood” 中的”ooo”和”o”。”o{0,1}”等价于”o?”。请注意在逗号和两个数之间不能有空格。 |
(pattern)
|
匹配pattern 并获取这一匹配。此时,整个表达式无论多复杂,都被视为一个单元。所获取的匹配可以从产生的 Match对象的group(id) 得到。要匹配圆括号字符,请使用 ‘\(‘ 或 ‘\)’。 |
(?:pattern)
|
非匹配型括号。相比普通括号,非匹配型括号只分组不捕获。这样一是可以避免不必要的捕获,提高效率,二是可以让代码可以更加清晰[例如,在捕获字符串中某个名字的时候,可能是group(1)或2、3…使用非匹配型括号,可以仅返回group(1)]。 |
(?=pattern)
|
肯定顺序环视。环视匹配的是特定位置,不匹配任何字符,也就是并不会“占用”字符。顺序环视从左到右匹配表达式,如果能匹配,则返回匹配成功信息。 |
(?!pattern)
|
否定顺序环视。从左到右匹配表达式,如果不能匹配,则返回匹配成功信息。 |
(?<=pattern)
|
肯定逆序环视,不支持。 |
(? |
否定逆序环视,不支持。 |
(?>pattern)
|
固化分组,不支持。 |
(?if then |else)
|
条件判断,不支持。 |
(? |
捕获文本到命名组,不支持。 |
(?#text)
|
注释,不支持。 |
\w
|
匹配包括下划线的任何单词字符。等价于”[A-Za-z0-9_]”。 |
\W
|
匹配任何非单词字符。等价于”[^A-Za-z0-9_]”。 |
\b
|
匹配单词(\w+)的边界(开始或末尾)。例如,对于字符串”never??!!”,”er\b”可以匹配”er”,”\bne”可以匹配”ne”。 |
\B
|
匹配单词(\w+)的非末尾,对于非单词(\W、\W+)字符没有意义。例如,对于字符串”never??!!”,表达式”ev\B”能匹配”ev”;表达式”\?\B”能匹配两个”?”,”\?!\B”能匹配”?!”,此时\B没有意义。 |
\cx
|
匹配由x指明的控制字符。例如,\cM匹配Control+M,等价于\r,\cI匹配\t,\cJ匹配\n,。x的值必须为A-Z或a-z之一。否则,将c视为一个原义的”c”字符。 |
\d
|
匹配一个数字字符。等价于 [0-9]。 |
\D
|
匹配一个非数字字符。等价于 [^0-9]。 |
\f
|
匹配一个换页符。等价于 \x0c 和 \cL。 |
\n
|
匹配一个换行符。等价于 \x0a 和 \cJ。 |
\r
|
匹配一个回车符。等价于 \x0d 和 \cM。 |
\s
|
匹配任何空白字符,包括空格、制表符、换页符等等。等价于[ \f\n\r\t\v]。 |
\S
|
匹配任何非空白字符。等价于[^ \f\n\r\t\v]。 |
\t
|
匹配一个制表符。等价于 \x09 和 \cI。 |
\v
|
匹配一个垂直制表符。等价于 \x0b 和 \cK。 |
\<
|
匹配单词开始位置,不支持。 |
\>
|
匹配单词结束位置,不支持。 |
\xn
|
匹配n,其中n为十六进制转义值。十六进制转义值必须为确定的两个数字长。例如,”\x41″匹配”A”。正则表达式中可以使用ASCII 编码。 |
\int
|
反向引用,int为一个正整数。匹配之前获取的、表达式匹配的文本。例如:”(a)(b)(c)\1\2\3″能够匹配”abcabc”。“\”元字符中,优先级为:反向引用>八进制Ascii值>原义字符。 |
\oct
|
标识一个八进制转义值或一个反向引用。如果之前至少 有otc个获取的子表达式,则otc为后向引用。否则,如果otc为八进制数字 (0-7),则otc为一个八进制转义值(具体查看ASCII 编码)。 |
\nm
|
标识一个八进制转义值或一个反向引用。如果 \nm 之前至少有nm个获取得子表达式,则nm为反向引用。如果 \nm之前至少有n个获取,则n为一个后跟文字m的反向引用。如果前面的条件都不满足,若n和m均为八进制数字(0-7),则\nm将匹配八进制转义值nm(具体查看ASCII 编码)。 |
\nml
|
如果 n 为八进制数字 (0-3),且 m 和 l 均为八进制数字 (0-7),则匹配八进制转义值 nml(具体查看ASCII 编码)。例如,”\101″能够匹配”A”。 |
\un
|
匹配n,其中n是一个用四个十六进制数字表示的 Unicode字符。例如,”\u00A9″匹配版权符号”©”。 |
[:flag:]
|
字符簇,如alnum、alpha、digit等,不支持。 |
\p{flag}
|
Unicode属性、字母表和区块,如InHanzi、Letter、Number等,不支持。 |
g、s、i、m、x、U
|
修饰符,用在正则表达式结尾,不支持。 |
区分大小写
|
设置RegExp中可选参数为caseSensitive。 |
多行匹配
|
当匹配的字符串是多行的时候,可设置RegExp可选参数multiLine。 |