曾经一直以为正则表达式(Regular Expression或Regex)过于复杂,无谓地增加程序阅读的复杂度,所以没有认真看过正则表达式的用法。在编程时,用一般的字符串操作函数,完全能够实现正则表达式的功能。最近,在CodeWars进行编程练习,遇到很多字符串匹配的问题。练习相关的几道题后发现,使用正则表达式解决字符串匹配类的问题,代码更加简洁、高效。因此,开始看正则表达式相关的资料,希望以后在CodeWars上能用得到。
正则表达式是一种特殊的字符串,用于描述一种字符串的模式,匹配一组(多个、很多个)字符串。比如,[tr]est
是一个正则表达式,能够匹配test
和rest
两个字符串。
正则表达式:[tr]est
字符串模式:字符串的第1个字符为t或T,第2个字符为e,第3个字符为s,第四个字符为T
字符串匹配是正则表达式最基本的功能。正则表达式需要一种正则引擎才能实现这样的功能。正则引擎是一种解析正则表达式的程序,它以正则表达式和普通字符串为输入,然后在普通字符串中搜索,判断其中是否存在字符串满足正则表达式所描述的模式。
普通字符、特殊字符、字符集合和字符组
字符是字符串的基本组成元素。正则表达式也是一种字符串,所以第一步就要讨论组成正则表达式的基本元素。普通字符就是特殊字符以为的字符,比如a-z
、A-Z
、0-9
、@!$%`等。一些不可打印的字符也可以归为普通字符。普通字符的特点是,一个普通字符就表示它本身;对于可打印字符,用户看见什么就代表什么;对于不可打印字符,就算用户看不见,它还是那个字符本身。
特殊字符是在正则表达式中不再是字符本身,而具有特定意义。比如[tr]est
中,[]
不表示中括号,而是构成一个字符集合。正则表达式的特殊字符包括[
、]
、\
、^
、$
、.
、|
、?
、*
、+
、(
、)
、{
、}
。\
是转移字符,如果普通字符中包含上述特殊字符,需要在特殊字符前添加转移字符。.
表示任意字符。
在[]
中所有字符组成一个字符集合。正则表达式中,字符集合出现的位置可以是所有字符中任意一个字符。比如[abcdef]string
中,[abcdef]
位于第1个字符的位置,因此如果一个字符串与该正则表达式匹配,它的第1个字符可以是abcdef
的任意一个。有意思的是,字符集合中很多特殊字符会被当成普通字符处理,只有^
、\
、-
还具有特殊意义。^
表示字符集合的逆;\
还是表示转义;-
表示连续的字符段,比如a-z
表示所有13个小写的字母。
在()
中所有字符组成一个子正则表达式,可以当成把它一个整体看待。如果后面添加重复操作符,()
会被当成一个整体进行重复。
位置匹配
某些匹配问题对字符串所处的位置也有一定的要求,比较常用的有起始位置、结束位置。
整个单词的匹配也是与位置相关匹配,即字符串位于单词的边界之间。
-
^
: 标记字符串的起始位置;

虽然标记为1
的This
和标记为2
的This
由相同的字符组成,但是它们所处的位置有所不同。前者位于整个字符串的起始位置,后者则不是。如果只想匹配位于起始位置的字符串,需要使用^
。因此,正则表达式^This
会匹配标记为1
的This
。
-
$
:标记字符串的结束位置;

虽然标记为1
的string
和标记为2
的string
由相同的字符组成,但是它们所处的位置有所不同。后者位于整个字符串的结束位置,前者则不是。如果只想匹配位于结束位置的字符串,需要使用$
。因此,正则表达式string$
会匹配标记为2
的string
。
-
\b
: 标记单词的边界。

标记为1
的is
和标记为2
的is
的不同在于,前者是单词This
的一部分,而后者是单独组成一个单词。在整词匹配过程中,使用正则表达式\bis\b
,只有标记2
的is
满足要求,其中\b
用于标记单词的边界。
单词的边界位置有4种情形:
1. 如果字符串不以字母字符开始,那么第一个字符前面位置是单词边界,比如'p1'位置。
2. 如果字符串不以字母字符结束,那么最后一个字符后面是单词边界,比如'p4'位置。
3. 非字母字符之后,字母字符之前为单词边界,比如'p2'位置。
4. 字母字符之后,非字母字符之前也为单词边界,比如'p3'位置。
重复字符/字符串
-
*
:前一个字符或字符串重复0次或多次。正则表达式abc*
能够匹配ab
,abc
,abcc
,abccccc
等字符串;
正则表达式z(abc)*
能够匹配z
,zabc
,zabcabc
,zabcabcabc
等字符串。 -
+
:前一个字符或字符串重复1次或多次。 -
?
:前一个字符或字符串重复0次或1次。 -
{min,max}
:前一个字符或字符串重复min至max次。
混合正则表达式
-
|
:用于组合多个正则表达式。regex1|regex2
能够在字符串中同时匹配regex1
和regex2
。
条件判断正则表达式
(?(?=regex)then|else)
如果if
部分能够匹配,正则引擎会尝试匹配then
部分;否则,尝试匹配else
部分。
(?(?=condition)(then1|then2|then3)|(else1|else2|else3))
网友评论