定义
正则表达式是一些用来匹配和处理文本的字符串。正则表达式是用正则表达式语言创建的。
完整的正则表达式由两种字符构成。”元字符“,其他为文字或者普通文本字符。
两种用途
- 搜索
- 替换
给定一个正则表达式,它要么匹配一些文本(进行一次搜索),要么匹配并替换一些文本(进行一次替换)
元字符列表
\ | 将下一个字符标记为特殊字符或字面值。例如,n 匹配字符 n,而 \n 匹配换行符。序列 \\ 匹配 \,而 \( 匹配 (。 |
^ | 匹配输入的开始部分。 |
$ | 匹配输入的结束部分。 |
* | 零次或更多次匹配前面的字符。例如,zo* 匹配 z 或 zoo。 |
+ | 一次或更多次匹配前面的字符。例如,zo+ 匹配 zoo,但是不匹配 z。 |
? | 零次或一次匹配前面的字符。例如,a?ve? 匹配 never 中的 ve。 |
. | 匹配任何单个字符,但换行符除外。 |
(pattern) | 匹配模式并记住匹配项。通过使用以下代码,匹配的子串可以检索自生成的匹配项集合:Item [0]…[n]。要匹配圆括号字符 ( ),请使用 \( 或 \)。 |
x|y | 匹配 x 或 y。 例如,z|wood 匹配 z 或 wood。(z|w)oo 匹配 zoo 或 wood。 |
{n} | n 是一个非负整数。精确匹配 n 次。例如,o{2} 不匹配 Bob 中的 o,但是匹配 foooood 中的前两个 o。 |
{n,} | 在此表达式中,n 是一个非负整数。至少 n 次匹配前面的字符。例如,o{2,} 不匹配 Bob 中的 o,但是匹配 foooood 中的所有 o。o{1,} 表达式等效于 o+,o{0,} 等效于 o*。 |
{n,m} | m 和 n 变量是非负整数。至少 n 次且至多 m 次匹配前面的字符。例如,o{1,3} 匹配 fooooood 中的前三个 o。o{0,1} 表达式等效于 o?。 |
[xyz] | 一个字符集。匹配任意一个包含的字符。例如,[abc] 匹配 plain 中的 a。 |
[^xyz] | 一个否定字符集。匹配任何未包含的字符。例如,[^abc] 匹配 plain 中的 p。 |
[a-z] | 字符范围。匹配指定范围中的任何字符。例如,[a-z] 匹配英语字母中的任何小写的字母字符。 |
[^m-z] | 一个否定字符范围。匹配未在指定范围中的任何字符。例如,[m-z] 匹配未在范围 m 到 z 之间的任何字符。 |
\A | 仅匹配字符串的开头。 |
\b | 匹配某个单词边界,即,某个单词和空格之间的位置。例如,er\b 匹配 never 中的 er,但是不匹配 verb 中的 er。 |
\B | 匹配非单词边界。ea*r\B 表达式匹配 never early 中的 ear。 |
\d | 匹配数字字符,等价于[0-9] |
\D | 匹配非数字字符,等价于[^0-9] |
\f | 匹配换页字符。 |
\n | 匹配换行符。 |
\r | 匹配回车字符。 |
\s | 匹配任何空格,包括空白、制表符、换页字符等等,等价于[\f\n\r\t\v]。 |
\S | 匹配任何非空格字符,等价于[^\f\n\r\t\v]。 |
\t | 匹配跳进字符。 |
\v | 匹配垂直跳进字符。 |
\w | 匹配任何单词字符,包括下划线。此表达式等效于 [A-Za-z0-9_]。 |
\W | 匹配任何非单词字符。此表达式等效于 [^A-Za-z0-9__]。 |
\z | 仅匹配字符串的结尾。 |
\Z | 仅匹配字符串的结尾,或者结尾的换行符之前。 |
POSIX字符类
注意:这里使用的模式以[[开头、以]]结束(两对方括号)。这是使用POSIX字符类所必须的。POSIX字符类必须括在[:和:]之间,我们使用的POSIX字符类是[:xdigit:](不是:xdigit:)。外层的[和]字符用来定义一个字符集合,内层的[和]字符是POSIX字符类本身的组成部分。
例如:[0-9A-Fz-f]就要替换为[[:xdigit:]]就得到这里的模式。它们的匹配结果完全一样。
常用的元字符
1:行的开始和结束
^ $ ^代表一行的开始 $代表一行的结束
^符号和$符号的特别之处就在于,它们匹配的是一个位置,而不是具体的文本
2:匹配任意字符
在正则表达式里,特殊字符(或字符集合)用来给出要搜索的东西。.字符可以匹配任何单个的字符、字母、数字甚至是.字符本身。
于是,用正则表达式c.t进行的搜索将匹配到cat和cot
3:匹配特殊字符
.字符在正则表达式里有着特殊的含义。如果模式里需要一个.,就要想办法来告诉正则表达式你需要的是.字符本身而不是它在正则表达式里的特殊含义。
为此,你必须在.的前面加上一个\(反斜杠)字符来对它进行转义。\是一个元字符(metacharacter,表示“这个字符有特殊含义,而不是字符本身含义”)。
4:匹配多个字符中的某一个
假如我们不需要匹配任意字符,我们只想匹配n和s这两个字符。在正则表达式里,我们可以使用元字符[和]来定义一个字符集合。
在使用[]定义的字符集合里,这两个元字符之间的所有字符都是该集合的组成部分,字符集合的匹配结果是能够与该集合里的任意一个成员相匹配的文本。
这里使用的正则表达式以[ns]开头;这个集合将匹配字符n或s(但不匹配字符c或其他字符)。[]不匹配任何字符,它们只负责定义一个字符集合。
5:多选结构
|是一个非常简洁的元字符,它的意思是或,依靠它,我们能够把不同的子表达式组合成一个总的表达式,而这个总的表达式又能够匹配任意的子表达式。例如apple|balana就表示匹配apple或者balana。
6:字符区间
那如果我们想匹配123456789,那是不是我们就要以[123456789]开头呢,这种形式的也可以成为字符区间。
在使用正则表达式的时候,会频繁地用到一些字符区间(0~9、A~Z,等等)。为了简化字符区间的定义,正则表达式提供了一个特殊的元字符——字符区间可以用-(连字符)来定义
模式[0-9]的功能与[0123456789]完全等价。字符区间并不仅限于数字,以下这些都是合法的字符区间:
- A-Z,匹配从A到Z的所有大写字母
- a-z,匹配从a到z的所有小写字母
提示 :在定义一个字符区间的时候,一定要避免让这个区间的尾字符小于它的首字符(例如[3-1])。这种区间是没有意义的,而且往往会让整个模式失效
注意: -(连字符)是一个特殊的元字符,作为元字符它只能用在[和]之间。在字符集合以外的地方,-只是一个普通字符,只能与-本身相匹配。因此,在正则表达式里,-字符不需要被转义。
在同一个字符集合里可以给出多个字符区间。比如说,下面这个模式可以匹配任何一个字母(无论大小写)或数字,但除此以外的其他字符(既不是数字也不是字母的字符)都不匹配:
[A-Za-z0-9]
7:取非匹配
字符集合通常用来指定一组必须匹配其中之一的字符。但在某些场合,我们需要反过来做,给出一组不需要得到的字符。换句话说,除了那个字符集合里的字符,其他字符都可以匹配。
最先想到的办法是,用一个字符集合把你需要的字符一一列举出来,但如果只需要把一小部分字符排除在外的话,那么做既麻烦又容易有遗漏。其实这里有一个更简明的办法:用元字符^来表明你想对一个字符集合进行取非匹配。
例如:[0-9]只匹配数字,而这里[^0-9]匹配的是任何不是数字的字符。
8:防止过度匹配
*和+都是所谓的“贪婪型”元字符,它们在进行匹配时的行为模式是多多益善而不是适可而止的。它们会尽可能地从一段文本的开头一直匹配到这段文本的末尾,而不是从这段文本的开头匹配到碰到第一个匹配时为止。
在不需要这种“贪婪行为”的时候该怎么办?答案是使用这些元字符的“懒惰型”版本(“懒惰”在这里的含义是匹配尽可能少的字符——与“贪婪型”元字符的行为模式刚好相反)。懒惰型元字符的写法很简单,只要给贪婪型元字符加上一个?后缀即可
9:子表达式
子表达式是一个更大的表达式的一部分;把一个表达式划分为一系列子表达式的目的是为了把那些子表达式当作一个独立元素来使用。子表达式必须用()括起来
提示:(和)是元字符。如果需要匹配()本身,就必须使用它的转义序列\(\)。
例如:( ){2,}
10:回溯引用匹配
假设你有一段文本,你想把这段文本里所有连续重复出现的单词(打字错误,其中有一个单词输了两遍)找出来。显然,在搜索某个单词的第二次出现时,这个单词必须是已知的。回溯引用允许正则表达式模式引用前面的匹配结果(具体到这个例子,就是前面匹配到的单词)。
例子:
$str = 'This is a block of of text
several words here are are
repeated and and they
should not be.';
preg_match_all('/[ ]+(\w+)[ ]+\1/', $str, $matches); echo "<pre/>"; print_r($matches);
Array ( [0] => Array ( [0] => of of [1] => are are [2] => and and ) [1] => Array ( [0] => of [1] => are [2] => and ) )
这个模式找到了我们想要的东西,但它是如何做到这一点的呢?[ ]+匹配一个或多个空格,\w+匹配一个或多个字母数字字符,[ ]+匹配随后的空格。
注意,\w+是括在括号里的,它是一个子表达式。这个子表达式不是用来进行重复匹配的,这里根本不涉及重复匹配的问题。
这个子表达式只是把整个模式的一部分单独划分出来以便在后面引用。这个模式的最后一部分是\1;这是一个回溯引用,而它引用的正是前面划分出来的那个子表达式:当(\w+)匹配到单词of的时候,\1也匹配单词of;当(\w+)匹配到单词and的时候,\1也匹配单词and。
\1到底代表着什么?它代表着模式里的第1个子表达式,\2代表着第2个子表达式、\3代表着第3个;依次类推。于是,在上面那个例子里,[ ]+(\w+)[ ]+\1将匹配同一个单词的连续两次重复出现。
提示:回溯引用匹配通常从1开始计数(\1、\2,等等)。在许多实现里,第0个匹配(\0)可以用来代表整个正则表达式。
11:回溯引用替换
如何将baidu.com替换成https://baidu.com
$str = 'this is baidu.com,this is baidu.com '; $replacement = '<a href="https://$1">$1</a>'; $str = preg_replace('/(baidu\.com)/', $replacement, $str); echo "<pre/>"; print_r($str); die;
this is baidu.com,this is baidu.com
替换操作需要用到两个正则表达式:一个用来给出搜索模式,另一个用来给出匹配文本的替换模式。
回溯引用可以跨模式使用,在第一个模式里被匹配的子表达式可以用在第二个模式里。
参考资料:
《正则表达式必知必会》