Skip to content

Latest commit

 

History

History
64 lines (40 loc) · 6.27 KB

005-字符类.md

File metadata and controls

64 lines (40 loc) · 6.27 KB

5.1 字符类(字符集)

字符类(也叫字符集),它的作用是匹配一组字符中的一个字符。字符集的语法很简单,只要把字符写到方括号中间就可以了。例如[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]teli[cs]en[cs]e。你可以用他来查找一个变量名,例如[A-Za-z_][A-Za-z_0-9]*。或者是一个C语言风格的十六进制数0[xX][A-Fa-f0-9]+

5.2 字符集取反操作(Negated Character Classes)

[后面加上一个脱字符^可以把字符集反向使用。它的作用是匹配任何一个不属于字符集的字符。和.符号不同,反向字符集可以匹配到不可见的行终结符,如果你不想匹配行终结符可以在字符集中加上行终结符,例如[^0-9\r\n]它可以匹配除了换行和数字以外的任何字符。

反向字符集任然需要匹配一个字符。q[^u]的含义并不是匹配一个后面不是u的q,它的含义是q的后面紧接着一个字符但是这个字符不是u。q[^u]并不能匹配Iraq中的q,它可以匹配Iraq is a country中的q空格,因为空格正好能和[^u]匹配。如果你只想匹配到q而不想匹配到后面的空格,你可是使用negative lookaheadq(?!u)。之后我们再讨论这个特性。

5.3 字符集中的元字符

在大多数正则引擎中,如果你在字符集中使用]\^-这四个元字符,那么你需要对这些元字符进行转义。其它的元字符则不需要转义。例如你可以使用[+*]匹配加号和星号,当然你也可以对所有的元字符进行转义,这并不会导致错误,只是这么做的话会降低正则表达式的可读性。

5.3.1 反斜杠转义

如果你要在字符集中匹配一个\,那么你需要对\进行转义。例如[\\x]可以匹配一个\或者一个x。对于]^-来说只要他们使用的位置不会造成歧义就不需要转义。

5.3.2 脱字符转义

对于脱字符^来说,只要他不是直接跟在[的后面就不需要转义。例如[x^]可以匹配一个x或者一个^

5.3.3 右侧方括号转义

对于]来说,只要他是紧跟着[或者^它就不需要转义。例如[]x]可以匹配]或者x,[^]x]可以匹配除了]x以外的任何字符。

在Javascript中以上规则不成立,[]不能匹配任何字符,[^]可以匹配任何字符。

5.3.4 -的转义

在以下情况下-不需要转义:

  • 紧接着[-,例如[-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.

5.4 字符集的量词匹配

如果你在字符集的后面使用量词(例如?*+),那么你会对整个字符集进行重复,而不是仅仅重复字符集匹配到的字符。例如[0-9]+可以同时匹配837222

如果你想对字符集的匹配结果使用量词,那么你可以使用backreferences。例如([0-9])\1+可以匹配222但是不能匹配837。如果用它匹配833337,它会匹配到3333,如果这不是你要的结果,可以使用lookaround

5.5 字符集的原理

在这一节中我们通过一个例子来解释字符集的解说过程。我们使用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

原文