字符类或字符集
字符类或字符集
使用"字符类"(也称为"字符集"),我们可以告诉正则表达式引擎仅匹配几个字符中的一个。只需将要匹配的字符放在方括号之间。如果要匹配a或e,请使用[ae]
。我们可以在gr[ae]y
中使用它来匹配字符串gray或grey。
字符类仅匹配一个字符。gr[ae]y
与graay ,graey或任何此类字符串不匹配。字符类中字符的顺序无关紧要。结果是相同的。 也就是说正则表达式 gr[ae]y
和 gr[ea]y
匹配结果是相同的。
我们可以在字符类中使用连字符来指定字符范围。[0-9]
匹配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]*
找到编程语言中的标识符。可以找到带有0[xX][A-Fa-f0-9]+
的C样式十六进制数。
否定字符类
在方括号中^
会对字符进行取反。结果是,字符类与不在字符类中的任何字符匹配。与.
不同,否定的字符类可以匹配换行符。如果我们不希望否定的字符类与换行符匹配,则需要在类中包括换行符。[^0-9\r\n]
匹配不是数字或换行符的任何字符。
重要的是要记住,否定的字符类仍然必须与字符匹配。q[^u]
不是意味着:"q 后面不跟着u"。它的意思是:" q后跟一个非u的字符"。它不可以与字符串Iraq中的q匹配。而且它也不可以和字符串unique中的q匹配。因为上面的正则表达式中被否定的字符类匹配的是“一个非u的任意字符”。如果要让正则表达式与两个字符串中的q和q仅匹配,则需要使用否定前瞻断言:q(?!u)
。我们稍后会讨论到。
字符类中的元字符
在大多数正则表达式中,字符类中特殊字符或元字符是[ ]
,反斜杠\
,^
和连字符-
。通常的元字符在一个字符类中都是一个普通字符字符,失去了自身的特殊性,不需要通过反斜杠转义。如果要搜索星号或加号,可以使用[+*]
。如果我们转义字符类中的常规元字符,虽然我们的正则表达式可以正常工作,但这样做会大大降低可读性。
要将反斜杠作为字符包含在内,而在字符类中没有任何特殊含义,则必须使用另一个反斜杠对其进行转义。[\\x]
匹配反斜杠或x。如果要想匹配 [ ]
,^
和连字符-
可以使用反斜杠转义,或者将其放在没有特殊含义的位置。POSIX和GNU是一个例外。他们将字符类中的反斜杠视为文字字符。因此,在这些正则引擎中,我们就无法在字符类中转义任何内容。
要将未转义的插入号^
作为文字包括在内,请将其放置在左括号之外的任何位置。[x^]
匹配x或^。这适用于本教程中讨论的所有正则表达式。
我们可以通过将未转义的右括号]放在左括号[
或^
之后。[]x]
匹配右括号]或x。[^]x]
匹配不是右括号或x的任何字符。这在JavaScript中不起作用,JavaScript将[]
视为始终无法匹配的空字符类,将[^]
视为与任何单个字符匹配的否定空字符类。Ruby将空字符类视为错误。因此,JavaScript和Ruby都要求使用反斜杠对右括号]进行转义,以将它们作为普通字符包含在字符类中。
连字符可以在左括号[之后,右括号]之前或^之后。既[-x]
和[x-]
匹配x或连字符。[^-x]
和[^x-]
匹配不是x或连字符的任何字符。这适用于本教程中讨论的所有正则表达式。字符类中无法形成范围的其他位置的连字符可能会解释为文字或错误。
在字符类之外的许多正则表达式标记也可以在字符类中使用。例如不可打印的字符,包括字符转义符,八进制转义符和十六进制转义符。对于支持Unicode的代码,它还包括Unicode字符转义符和Unicode属性。[$\u20AC]匹配$或欧元符号,假设我们的正则表达式支持Unicode转义。
重复字符类
如果使用?
,*
或+
运算符量词使字符类重复的话,我们将重复整个字符类。而不只是在重复与之匹配的字符。正则表达式[0-9]+
可以匹配876和222 。
如果要重复匹配的字符,则需要使用反向引用。([0-9])\1+
匹配222,但不匹配876 。当应用于字符串833337时,它将与该字符串中间的3333匹配。
正则表达式引擎内核
如前所述:字符类中字符的顺序无关紧要。gr[ae]y
匹配目标字符串Is his hair grey or gray?中的“grey”,这是因为最左匹配原则。我们已经看到引擎如何应用仅包含文字字符的正则表达式。现在,我们将看到它如何应用具有多个排列的正则表达式。也就是说:gr[ae]y
可以同时匹配gray和grey 。
对于字符串的前十二个字符,没有任何值得注意的事情发生。引擎在每一步都无法匹配g ,而是继续字符串中的下一个字符。当引擎到达第13个字符时,g被匹配。然后,引擎尝试将正则表达式的其余部分与文本进行匹配。正则表达式中的下一个token是r
,它与文本中的下一个字符匹配。因此,尝试在字符(e )的下一个字符处尝试第三个token [ae]
。字符类为引擎提供了两个选项:match a或match e 。它首先试图匹配一个,而失败。
但是,因为我们使用的是正则表达式控制的引擎,所以在确定正则表达式不能与以字符13开始的文本匹配之前,它必须继续尝试匹配正则表达式模式的所有其他排列。因此,它将继续使用其他选项,以及发现e
与e匹配。最后一个正则表达式标记是y ,它也可以与以下字符匹配。引擎找到了与第13个字符开头的文本完全匹配的结果。它返回grey作为匹配结果,并且看起来没有任何变化。同样,即使我们将a放在字符类的最前面,也将返回最左边的匹配,并且字符串中可能已经匹配了gray。但是引擎根本没有走那么远,因为在它的左侧发现了另一个同样有效的匹配项。仅当我们告诉正则表达式引擎在第一个匹配项之后继续在目标字符串的其余部分中查找第二个匹配项时,才会匹配gray 。
练习题
关于字符类我们提供了相关的一些练习题,可以加深我们对字符类的掌握 点此去练习