字符类(也叫字符集),它的作用是匹配一组字符中的一个字符。字符集的语法很简单,只要把字符写到方括号中间就可以了。例如[ae]
可以匹配a
或者e
。你可以用gr[ae]y
匹配gray
或者grey
。gray是美式英语,grey是英式英语。
一个字符集只能匹配一个字符。例如gr[ae]y
不能匹配graay
或者graey
。字符集中的字符排序是不分先后的,不同的顺序匹配结果是一样的。
你可以使用-
来表示一个范围。例如[0-9]
可以匹配数字字符。你可以同时使用多个范围,例如[0-9a-fA-F]
可以匹配一个十六进制字符。你也可以把单个字符和范围组合起来,例如[0-9a-fxA-FX]
可以匹配一个十六进制字符或者一个x。和之前一样组合的顺序对最终的结果没有影响。
字符集是正则表达式中最常用的特性之一。你可以用它来匹配一个存在拼写错误的单词,例如sep[ae]r[ae]te
和li[cs]en[cs]e
。你可以用他来查找一个变量名,例如[A-Za-z_][A-Za-z_0-9]*
。或者是一个C语言风格的十六进制数0[xX][A-Fa-f0-9]+
在[
后面加上一个脱字符^
可以把字符集反向使用。它的作用是匹配任何一个不属于字符集的字符。和.
符号不同,反向字符集可以匹配到不可见的行终结符,如果你不想匹配行终结符可以在字符集中加上行终结符,例如[^0-9\r\n]
它可以匹配除了换行和数字以外的任何字符。
反向字符集任然需要匹配一个字符。q[^u]
的含义并不是匹配一个后面不是u的q,它的含义是q的后面紧接着一个字符但是这个字符不是u。q[^u]
并不能匹配Iraq
中的q
,它可以匹配Iraq is a country
中的q空格
,因为空格正好能和[^u]
匹配。如果你只想匹配到q
而不想匹配到后面的空格,你可是使用negative lookahead:q(?!u)
。之后我们再讨论这个特性。
在大多数正则引擎中,如果你在字符集中使用]
、\
、^
、-
这四个元字符,那么你需要对这些元字符进行转义。其它的元字符则不需要转义。例如你可以使用[+*]匹配加号和星号,当然你也可以对所有的元字符进行转义,这并不会导致错误,只是这么做的话会降低正则表达式的可读性。
如果你要在字符集中匹配一个\
,那么你需要对\
进行转义。例如[\\x]
可以匹配一个\
或者一个x
。对于]
、^
、-
来说只要他们使用的位置不会造成歧义就不需要转义。
对于脱字符^
来说,只要他不是直接跟在[
的后面就不需要转义。例如[x^]
可以匹配一个x或者一个^
。
对于]
来说,只要他是紧跟着[
或者^
它就不需要转义。例如[]x]
可以匹配]
或者x,[^]x]
可以匹配除了]
和x
以外的任何字符。
在Javascript中以上规则不成立,
[]
不能匹配任何字符,[^]
可以匹配任何字符。
在以下情况下-
不需要转义:
- 紧接着
[
的-
,例如[-x]
]
前面的-
,例如[x-]
- 紧接着
^
的-
,例如[^-x]
、[^x-]
在其他的地方使用-
,如果不能形成一个范围的话,有可能导致一个错误,也有可能把-
作为字面量字符处理。这这一点上,各种引擎的处理方式并不统一。
如果你使用的引擎支持Unicode,你也可以在字符集中使用Unicode,例如[\u20AC]
。
待翻译:
Many regex tokens that work outside character classes can also be used inside character classes. This includes character escapes, octal escapes, and hexadecimal escapes for non-printable characters. For flavors that support Unicode, it also includes Unicode character escapes and Unicode properties. [$\u20AC] matches a dollar or euro sign, assuming your regex flavor supports Unicode escapes.
如果你在字符集的后面使用量词(例如?
、*
、+
),那么你会对整个字符集进行重复,而不是仅仅重复字符集匹配到的字符。例如[0-9]+
可以同时匹配837
和222
。
如果你想对字符集的匹配结果使用量词,那么你可以使用backreferences。例如([0-9])\1+
可以匹配222但是不能匹配837。如果用它匹配833337,它会匹配到3333,如果这不是你要的结果,可以使用lookaround
在这一节中我们通过一个例子来解释字符集的解说过程。我们使用gr[ae]y
去匹配Is his hair grey or gray?
,结果将匹配到grey。之前我们学习过字面量字符的匹配过程,现在我们来看一下具有多种排列方式的字符集是如何匹配的。
在匹配的过程中,前12个字符都没有匹配成功,因为它们都不能和g
匹配。直到第13个字符字符g终于和正则表达式的第一tokeng
匹配成功。下一步引擎将表达式的剩余部分和字符串匹配,这时r也匹配成功了。接下来引擎将[ae]
和字符e匹配,因为这个token是字符集,所以引擎会把字符集中的所有组合与字符串中的下一个字符e匹配。首先是用a
和字符e匹配,这一次没有匹配成功,但是此时还不能确定这个字符串的第13个字符作为起始是否能和表达式匹配,因为还有另一个排列需要尝试。接下来引擎使用字符集中的第二个tokene
,这一次匹配成功了。接下来正则引擎进行下一个tokeny
的匹配,同样也匹配成功了。
到这一步位置整个正则表达式已经匹配完成了。你可能已经注意到字符串中的gray
也可以匹配成功,但是根据正则引擎的最左原则,引擎不会继续匹配下一个可能的结果。除非你通过函数调用告诉引擎进行第二次匹配。
如果文章出现错误,请给我提Issues - - Github地址
需要进一步翻译的内容:
- backreferences
- lookaround