正则表达式详细介绍

简介

正则表达式又称规则表达式。(英语:Regular Expression,在代码中常简写为regex、regexp或RE),正则表达式通常被用来检索、替换那些符合某个模式(或规则)的文本。

许多程序设计语言都支持利用正则表达式进行字符串操作。例如,在Perl中就内建了一个功能强大的正则表达式引擎。正则表达式这个概念最初是由Unix中的工具软件(sed和grep)普及开来的。

概念

正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个规则字符串,这个规则字符串用来表达对字符串的一种过滤逻辑

特点

  1. 灵活性、逻辑性和功能性非常强
  2. 可以迅速地用极简单的方式达到字符串的复杂控制
  3. 对于刚接触的人来说,比较晦涩难懂

引擎

正则引擎主要可以分为两大类:一种是DFA,另一种是NFA。这两种引擎都有了很久的历史(至今二十多年),当中也由这两种引擎产生了很多变体!于是POSIX的出台规避了不必要变体的继续产生。这样一来,主流的正则引擎又分为3类:一、DFA,二、传统型NFA,三、POSIX NFA。

  1. DFA引擎在线性时状态下执行,因为它们不要求回溯(并因此它们永远不测试相同的字符两次)。DFA 引擎还可以确保匹配最长的可能的字符串。但是,因为 DFA 引擎只包含有限的状态,所以它不能匹配具有反向引用的模式;并且因为它不构造显示扩展,所以它不可以捕获子表达式。
  2. 传统的NFA引擎运行所谓的“贪婪的”匹配回溯算法,以指定顺序测试正则表达式的所有可能的扩展并接受第一个匹配项。因为传统的 NFA 构造正则表达式的特定扩展以获得成功的匹配,所以它可以捕获子表达式匹配和匹配的反向引用。但是,因为传统的 NFA 回溯,所以它可以访问完全相同的状态多次(如果通过不同的路径到达该状态)。因此,在最坏情况下,它的执行速度可能非常慢。因为传统的 NFA 接受它找到的第一个匹配,所以它还可能会导致其他(可能更长)匹配未被发现。
  3. POSIX NFA引擎与传统的 NFA 引擎类似,不同的一点在于:在它们可以确保已找到了可能的最长的匹配之前,它们将继续回溯。因此,POSIX NFA 引擎的速度慢于传统的 NFA 引擎。

对使用不同引擎的软件分类

  1. 使用DFA引擎的程序主要有:awk, egrep, flex,lex, MySQL, Procmail等;
  2. 使用传统型NFA引擎的程序主要有:GNU Emacs, Java, ergp, less, more, .NET,PCRE library, Perl, PHP, Python, Ruby, sed, vi;
  3. 使用POSIX NFA引擎的程序主要有:mawk, Mortice Kern Systems’ utilities, GNU Emacs(使用时可以明确指定);
  4. 使用DFA/NFA混合的引擎:GNU awk, GNU grep/egrep, Tcl。

NFA与DFA工作的区别

如果对字符串 this is yansen’s blog 使用正则表达式伪码 /ya(msen|nsen|nsem)/

  • NFA工作方式是先在字符串中查找 y 然后匹配其后是否为 a,如果是 a 则继续,查找其后是否为 m 如果不是则匹配其后是否为 n(此时淘汰msen选择分支)。然后继续看其后是否依次为 se,接着测试是否为 n,是 n 则匹配成功,不是则测试是否为 m。 为什么是 m?因为 NFA 工作方式是以正则表达式为标准,反复测试字符串,这样同样一个字符串有可能被反复测试了很多次!
  • 而DFA则不是如此,DFA会从 this 中 t 开始依次查找 y,定位到 y,已知其后为 a,则查看表达式是否有 a,此处正好有 a。然后字符串 a 后为 n,DFA依次测试表达式,此时 msen 不符合要求淘汰。nsennsem 符合要求,然后DFA依次检查字符串,检测到 sen 中的 n 时只有 nsen 分支符合,则匹配成功!

由此可以看出来,两种引擎的工作方式完全不同,NFA以表达式为主导,DFA以文本为主导!一般而论,DFA引擎则搜索更快一些!但是NFA以表达式为主导,反而更容易操纵。两种引擎各有所长,而真正的引用则取决与你的需要以及所使用的语言!

语法

一个正则表达式通常被称为一个模式(pattern),为用来描述或者匹配一系列匹配某个句法规则的字符串。例如:HandelHändelHaendel 这三个字符串,都可以由 H(a|ä|ae)ndel 这个模式来描述。

普通字符

普通字符包括没有显式指定为元字符的所有可打印和不可打印字符。这包括所有大写和小写字母、所有数字、所有标点符号和一些其他符号。

非打印字符

非打印字符也可以是正则表达式的组成部分。下表列出了表示非打印字符的转义序列:

字符 描述
\cx 匹配由x指明的控制字符。例如, \cM 匹配一个 Control-M 或回车符。x 的值必须为 A-Z 或 a-z 之。否则,将 c 视为一个原义的 c 字符。
\f 匹配一个换页符。等价于 \x0c 和 \cL。
\n 匹配一个换行符。等价于 \x0a 和 \cJ。
\r 匹配一个回车符。等价于 \x0d 和 \cM。
\s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]
\S 匹配任何非空白字符。等价于 [^ \f\n\r\t\v]
\t 匹配一个制表符。等价于 \x09 和 \cI。
\v 匹配一个垂直制表符。等价于 \x0b 和 \cK。

特殊字符

一些有特殊含义的字符,若要匹配这些特殊字符,必须首先使字符转义,即将反斜杠字符 \ 放在它们前面。下表列出了正则表达式中的特殊字符:

字符 描述
$ 匹配输入字符串的结尾位置。如果设置了 RegExp 对象的 Multiline 属性,则 $ 也匹配 \n\r。要匹配 $ 字符本身,请使用 \$
( ) 标记一个子表达式的开始和结束位置。子表达式可以获取供以后使用。要匹配这些字符,请使用 \(\)
* 匹配前面的子表达式零次或多次。要匹配 * 字符,请使用 \*
+ 匹配前面的子表达式一次或多次。要匹配 + 字符,请使用 \+
. 匹配除换行符 \n之外的任何单字符。要匹配 .,请使用 \.
[ 标记一个中括号表达式的开始。要匹配 [,请使用 \[
? 匹配前面的子表达式零次或一次,或指明一个非贪婪限定符。要匹配 ? 字符,请使用 \?
\ 将下一个字符标记为或特殊字符、或原义字符、或向后引用、或八进制转义符。例如, ‘n’ 匹配字符’n’。'\n' 匹配换行符。序列 '\\' 匹配 "\",而 '\(' 则匹配 "("
^ 匹配输入字符串的开始位置,除非在方括号表达式中使用,此时它表示不接受该字符集合。要匹配 ^ 字符本身,请使用 \^
{ 标记限定符表达式的开始。要匹配 {,请使用 \{

限定符

限定符用来指定正则表达式的一个给定组件必须要出现多少次才能满足匹配,其中 *、+和? 限定符都是’’’贪婪’’’的,因为它们会尽可能多的匹配文字,只有在它们的后面加上一个 ? 就可以实现非贪婪或最小匹配。

字符 描述
* 匹配前面的子表达式零次或多次。例如,zo* 能匹配 "z" 以及 "zoo"* 等价于{0,}
+ 匹配前面的子表达式一次或多次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"+ 等价于 {1,}
? 匹配前面的子表达式零次或一次。例如,"do(es)?" 可以匹配 "do""does" 中的 "do"? 等价于 {0,1}
{n} n 是一个非负整数。匹配确定的 n 次。例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food" 中的两个 o
{n,} n 是一个非负整数。至少匹配 n次。例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood" 中的所有 o'o{1,}' 等价于 'o+''o{0,}' 则等价于 'o*'
{n,m} m 和 n 均为非负整数,其中 n <= m。最少匹配 n 次且最多匹配 m 次。例如,"o{1,3}" 将匹配 "fooooood" 中的前三个 o'o{0,1}' 等价于 'o?'。请注意在逗号和两个数之间不能有空格。

定位符

定位符用来描述字符串或单词的边界,使正则表达式固定到行首或行尾。

字符 描述
^ 匹配输入字符串开始的位置。如果设置了 RegExp 对象的 Multiline 属性,^ 还会与 \n\r 之后的位置匹配。
$ 匹配输入字符串结尾的位置。如果设置了 RegExp 对象的 Multiline 属性,$ 还会与 \n\r 之前的位置匹配。
\b 匹配一个字边界,即 与空格间的位置。
\B 非字边界匹配。

不能将限定符与定位符一起使用。由于在紧靠换行或者字边界的前面或后面不能有一个以上位置,因此不允许诸如 ^* 之类的表达式。

模式修正符号

对整个正则表达式使用,是表达式功能的扩展

字符 描述
i 不区分大小写
m 将字符串视为一行
s 将字符视为单行,允许.匹配换行
x 忽略模式中的空格
e 替换
A ^
B $
U 禁用贪婪特征,类似?

选择

用圆括号将所有选择项括起来,相邻的选择项之间用 | 分隔。例如 gray|grey 可以匹配 greygray

反向引用

对一个正则表达式模式或部分模式两边添加圆括号将导致相关匹配存储到一个临时缓冲区中,所捕获的每个子匹配都按照在正则表达式模式中从左到右出现的顺序存储。缓冲区编号从 1 开始,最多可存储 99 个捕获的子表达式。每个缓冲区都可以使用 '\n' 访问,其中 n 为一个标识特定缓冲区的一位或两位十进制数。可以使用非捕获元字符 '?:''?=''?!' 来重写捕获,忽略对相关匹配的保存。

    1. `/Windows(?!95|98|NT|2000)/g` `Windows`3.1 Windows95 Windows98 和 WindowsNT 1. `/Windows(?=95|98|NT|2000)/g` Windows3.1 `Windows`95 `Windows`98 和 `Windows`NT 1. `/Windows(?:95|98|NT|2000)/g` Windows3.1 `Windows95` `Windows98` 和 `WindowsNT`

元字符

字符 描述
\ 将下一个字符标记为一个特殊字符、或一个原义字符、或一个向后引用、或一个八进制转义符。例如,“n”匹配字符“n”。“\n”匹配一个换行符。序列“\”匹配“\”而“(”则匹配“(”。
!^ 匹配输入字符串的开始位置。如果设置了!RegExp对象的Multiline属性,!^也匹配“\n”或“\r”之后的位置。
$ 匹配输入字符串的结束位置。如果设置了!RegExp对象的Multiline属性,$也匹配“\n”或“\r”之前的位置。
* 匹配前面的子表达式零次或多次。例如,zo能匹配“z”、“zo”以及“zoo”。等价于{0,}。
+ 匹配前面的子表达式一次或多次。例如,“zo+”能匹配“zo”以及“zoo”,但不能匹配“z”。+等价于{1,}。
? 匹配前面的子表达式零次或一次。例如,“do(es)?”可以匹配“do”或“does”中的“do”。?等价于{0,1}。
{”n”} ”n”是一个非负整数。匹配确定的”n”次。例如,“o!{2}”不能匹配“Bob”中的“o”,但是能匹配“food”中的两个o。
{”n”,} ”n”是一个非负整数。至少匹配”n”次。例如,“o{2,}”不能匹配“Bob”中的“o”,但能匹配“foooood”中的所有o。“o{1,}”等价于“o+”。“o{0,}”则等价于“o*”。
{”n”,”m”} ”m”和”n”均为非负整数,其中”n”<=”m”。最少匹配”n”次且最多匹配”m”次。例如,“o{1,3}”将匹配“fooooood”中的前三个o。“o{0,1}”等价于“o?”。请注意在逗号和两个数之间不能有空格。
? 当该字符紧跟在任何一个其他限制符(*,+,?,{”n”},{”n”,},{”n”,”m”})后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串“oooo”,“o+?”将匹配单个“o”,而“o+”将匹配所有“o”。
. 匹配除“\n”之外的任何单个字符。要匹配包括“\n”在内的任何字符,请使用像“(.
(pattern) 匹配pattern并获取这一匹配的子字符串。该子字符串用于向后引用。所获取的匹配可以从产生的Matches集合得到,在VBScript中使用!SubMatches集合,在JScript中则使用0…0…9属性。要匹配圆括号字符,请使用“(”或“)”。
(?:pattern) 匹配pattern但不获取匹配的子字符串,也就是说这是一个非获取匹配,不存储匹配的子字符串用于向后引用。这在使用或字符“(
(?=pattern) 正向肯定预查,在任何匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如,“Windows(?=95
(?!pattern) 正向否定预查,在任何不匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如“Windows(?!95
(?<=pattern) 反向肯定预查,与正向肯定预查类似,只是方向相反。例如,“(?<=95
(? 反向否定预查,与正向否定预查类似,只是方向相反。例如“(?
x y
[xyz] 字符集合(character class)。匹配所包含的任意一个字符。例如,“[abc]”可以匹配“plain”中的“a”。特殊字符仅有反斜线\保持特殊含义,用于转义字符。其它特殊字符如星号、加号、各种括号等均作为普通字符。脱字符!^如果出现在首位则表示负值字符集合;如果出现在字符串中间就仅作为普通字符。连字符 - 如果出现在字符串中间表示字符范围描述;如果如果出现在首位则仅作为普通字符。
[!^xyz] 排除型(negate)字符集合。匹配未列出的任意字符。例如,“[!^abc]”可以匹配“plain”中的“plin”。
[a-z] 字符范围。匹配指定范围内的任意字符。例如,“[a-z]”可以匹配“a”到“z”范围内的任意小写字母字符。
[!^a-z] 排除型的字符范围。匹配任何不在指定范围内的任意字符。例如,“[!^a-z]”可以匹配任何不在“a”到“z”范围内的任意字符。
\b 匹配一个单词边界,也就是指单词和空格间的位置。例如,“er\b”可以匹配“never”中的“er”,但不能匹配“verb”中的“er”。
\B 匹配非单词边界。“er\B”能匹配“verb”中的“er”,但不能匹配“never”中的“er”。
\cx 匹配由x指明的控制字符。例如,\cM匹配一个Control-M或回车符。x的值必须为A-Z或a-z之一。否则,将c视为一个原义的“c”字符。
\d 匹配一个数字字符。等价于![0-9]。
\D 匹配一个非数字字符。等价于[!^0-9]。
\f 匹配一个换页符。等价于\x0c和\cL。
\n 匹配一个换行符。等价于\x0a和\cJ。
\r 匹配一个回车符。等价于\x0d和\cM。
\s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于[ \f\n\r\t\v]。
\S 匹配任何非空白字符。等价于[!^ \f\n\r\t\v]。
\t 匹配一个制表符。等价于\x09和\cI。
\v 匹配一个垂直制表符。等价于\x0b和\cK。
\w 匹配包括下划线的任何单词字符。等价于“[A-Za-z0-9_]”。
\W 匹配任何非单词字符。等价于“[!^A-Za-z0-9_]”。
\x”n” 匹配”n”,其中”n”为十六进制转义值。十六进制转义值必须为确定的两个数字长。例如,“\x41”匹配“A”。“\x041”则等价于“\x04&1”。正则表达式中可以使用ASCII编码。.
\”num” 向后引用(back-reference)一个子字符串(substring),该子字符串与正则表达式的第num个用括号围起来的子表达式(subexpression)匹配。其中num是从1开始的正整数,其上限可能是99。例如:“(.)\1”匹配两个连续的相同字符。
\”n” 标识一个八进制转义值或一个向后引用。如果\”n”之前至少”n”个获取的子表达式,则”n”为向后引用。否则,如果”n”为八进制数字(0-7),则”n”为一个八进制转义值。
\”nm” 标识一个八进制转义值或一个向后引用。如果\”nm”之前至少有”nm”个获得子表达式,则”nm”为向后引用。如果\”nm”之前至少有”n”个获取,则”n”为一个后跟文字”m”的向后引用。如果前面的条件都不满足,若”n”和”m”均为八进制数字(0-7),则\”nm”将匹配八进制转义值”nm”。
\”nml” 如果”n”为八进制数字(0-3),且”m和l”均为八进制数字(0-7),则匹配八进制转义值”nm”l。
\u”n” 匹配”n”,其中”n”是一个用四个十六进制数字表示的Unicode字符。例如,\u00A9匹配版权符号(©)。

优先级

正则表达式从左到右进行计算,并遵循优先级顺序,这与算术表达式非常类似。

字符 描述
最高 \
(), (?:), (?=), []
*, +, ?, {n}, {n,}, {n,m}
^, $
最低 `

示例

javascript

示例1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
var sourceStr = 'The best things in life are free';
var patt1 = new RegExp("e");
//test() 方法检索字符串中的指定值。返回值是 true 或 false。
document.write(patt1.test(sourceStr));
document.write('<br>-------------<br>');

//exec() 方法检索字符串中的指定值。返回值是被找到的值。如果没有发现匹配,则返回 null。
document.write(patt1.exec(sourceStr));
document.write('<br>-------------<br>');

//如果需要找到所有某个字符的所有存在,则可以使用 "g" 参数 ("global")。
var patt2 = new RegExp("e", "g");
do {
result = patt2.exec(sourceStr);
document.write(result + ', ');
} while (result != null)
document.write('<br>-------------<br>');

//用于改变 RegExp
patt1.compile("d");
document.write(patt1.test(sourceStr));

//简化使用
var patt3 = /e/;
document.write(patt3.test(sourceStr));
1
2
3
4
5
6
7
8
9
true
-------------
e
-------------
e, e, e, e, e, e, null,
-------------
false
-------------
true

示例2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//search() 方法用于检索字符串中指定的子字符串,或检索与正则表达式相匹配的子字符串,它对对大小写敏感。
var sourceStr = 'The best things in life are free';
document.write(sourceStr.search(/E/i));
document.write('<br>-------------<br>');

//match() 方法可在字符串内检索指定的值,或找到一个或多个正则表达式的匹配。
document.write(sourceStr.match(/n\w{1}/));
document.write('<br>-------------<br>');
document.write('1 plus 2 equal 3'.match(/\d/g));
document.write('<br>-------------<br>');

//replace() 方法用于在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串。
document.write(sourceStr.replace(/e/, '#'));
document.write('<br>-------------<br>');
document.write(sourceStr.replace(/e/g, '#'));
document.write('<br>-------------<br>');
document.write('Doe, John'.replace(/(\w+)\s*,\s*(\w+)/, "$2 $1"));
document.write('<br>-------------<br>');
//把字符串中所有单词的首字母都转换为大写
var tmpStr = sourceStr.replace(/\b\w+\b/g, function (word) {
return word.substring(0, 1).toUpperCase() + word.substring(1);
}
);
document.write(tmpStr);
document.write('<br>-------------<br>');

//split() 方法用于把一个字符串分割成字符串数组
document.write(sourceStr.split(' '));
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
-------------
ng
-------------
1,2,3
-------------
Th# best things in life are free
-------------
Th# b#st things in lif# ar# fr##
-------------
John Doe
-------------
The Best Things In Life Are Free
-------------
The,best,things,in,life,are,free

php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
/*
preg_filter — 执行一个正则表达式搜索和替换
preg_grep — 返回匹配模式的数组条目
preg_last_error — 返回最后一个PCRE正则执行产生的错误代码
preg_match_all — 执行一个全局正则表达式匹配
preg_match — 执行一个正则表达式匹配
preg_quote — 转义正则表达式字符
preg_replace_callback_array — Perform a regular expression search and replace using callbacks
preg_replace_callback — 执行一个正则表达式搜索并且使用一个回调进行替换
preg_replace — 执行一个正则表达式的搜索和替换
preg_split — 通过一个正则表达式分隔字符串
*/
$subject = 'The best things in life are free';
$pattern = '/e/';
if (preg_match($pattern, $subject, $matches)) {
var_dump($matches);
} else {
echo('没有匹配结果');
}
unset($matches);
echo '<br>-------------<br>';

$pattern = '/e/';
if (preg_match_all($pattern, $subject, $matches)) {
var_dump($matches);
} else {
var_dump('没有匹配结果');
}
unset($matches);
echo '<br>-------------<br>';

$subject = 'http:/www.xxx.com/index.html?r=seller/index/list';
$pattern = '/http:\/([a-z]{1,3}\.[a-z]{1,}\.[a-z]{2,3})\/(\w+\.html)\?r=[a-z]{1,}\/[a-z]{1,}\/[a-z]{1,}/';
if (preg_match_all($pattern, $subject, $matches)) {
var_dump($matches);
} else {
var_dump('没有匹配结果');
}
unset($matches);
echo '<br>-------------<br>';
?>
1
2
3
4
5
6
array(1) { [0]=> string(1) "e" } 
-------------
array(1) { [0]=> array(6) { [0]=> string(1) "e" [1]=> string(1) "e" [2]=> string(1) "e" [3]=> string(1) "e" [4]=> string(1) "e" [5]=> string(1) "e" } }
-------------
array(3) { [0]=> array(1) { [0]=> string(51) "http:/www.xxx.com/index.html?r=seller/index/list" } [1]=> array(1) { [0]=> string(14) "www.xxx.com" } [2]=> array(1) { [0]=> string(10) "index.html" } }
-------------

java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.company;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main {

public static void main(String[] args) {
Pattern p = Pattern.compile("e");
Matcher m = p.matcher("The best things in life are free");
System.out.println(m.replaceAll("#"));
System.out.println("-------------");

Pattern p2 = Pattern.compile("http:\\/([a-z]{1,3}\\.[a-z]{1,}\\.[a-z]{2,3})\\/(\\w+\\.html)\\?r=[a-z]{1,}\\/[a-z]{1,}\\/[a-z]{1,}");
Matcher m2 = p2.matcher("http:/www.xxx.com/index.html?r=seller/index/list");
m2.find();
System.out.println(m2.group(0));
System.out.println(m2.group(1));
System.out.println(m2.group(2));
System.out.println("-------------");
}
}
1
2
3
4
5
6
Th# b#st things in lif# ar# fr##
-------------
http:/www.xxx.com/index.html?r=seller/index/list
www.xxx.com
index.html
-------------

c++

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <string>
#include <regex>

using namespace std;

int main() {
string s("The best things in life are free");
regex e("e");
cout << regex_replace (s, e, "#") << endl;

string s2("http:/www.xxx.com/index.html?r=seller/index/list");
regex e2("http:\\/([a-z]{1,3}\\.[a-z]{1,}\\.[a-z]{2,3})\\/(\\w+\\.html)\\?r=[a-z]{1,}\\/[a-z]{1,}\\/[a-z]{1,}");
smatch m;
regex_search(s2, m, e2);
for (auto x : m) {
cout << x << "\n";
}
cout << endl;
}
1
2
3
4
Th# b#st things in lif# ar# fr##
http:/www.xxx.com/index.html?r=seller/index/list
www.xxx.com
index.html

python

1
2
3
4
5
6
7
8
9
import re

p = re.compile('e')
s = 'The best things in life are free'
print(p.sub('#', s))

s2 = 'http:/www.xxx.com/index.html?r=seller/index/list'
m = re.match('http:\\/([a-z]{1,3}\\.[a-z]{1,}\\.[a-z]{2,3})\\/(\\w+\\.html)\\?r=[a-z]{1,}\\/[a-z]{1,}\\/[a-z]{1,}', s2)
print(m.group(0, 1, 2))
1
2
Th# b#st things in lif# ar# fr##
('http:/www.xxx.com/index.html?r=seller/index/list', 'www.xxx.com', 'index.html')

常用正则表达式

数字表达式

  1. 数字:^[0-9]*$
  2. n位的数字:^\d{n}$
  3. 至少n位的数字:^\d{n,}$
  4. m-n位的数字:^\d{m,n}$
  5. 零和非零开头的数字:^(0|[1-9][0-9]*)$
  6. 非零开头的最多带两位小数的数字:^([1-9][0-9]*)+(.[0-9]{1,2})?$
  7. 带1-2位小数的正数或负数:^(\-)?\d+(\.\d{1,2})?$
  8. 正数、负数、和小数:^(\-|\+)?\d+(\.\d+)?$
  9. 有两位小数的正实数:^[0-9]+(.[0-9]{2})?$
  10. 有1~3位小数的正实数:^[0-9]+(.[0-9]{1,3})?$
  11. 非零的正整数:^[1-9]\d*$^([1-9][0-9]*){1,3}$^\+?[1-9][0-9]*$
  12. 非零的负整数:^\-[1-9][]0-9"*$^-[1-9]\d*$
  13. 非负整数:^\d+$^[1-9]\d*|0$
  14. 非正整数:^-[1-9]\d*|0$^((-\d+)|(0+))$
  15. 非负浮点数:^\d+(\.\d+)?$ 或 ^[1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0$
  16. 非正浮点数:^((-\d+(\.\d+)?)|(0+(\.0+)?))$^(-([1-9]\d*\.\d*|0\.\d*[1-9]\d*))|0?\.0+|0$
  17. 正浮点数:^[1-9]\d*\.\d*|0\.\d*[1-9]\d*$^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$
  18. 负浮点数:^-([1-9]\d*\.\d*|0\.\d*[1-9]\d*)$^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$
  19. 浮点数:^(-?\d+)(\.\d+)?$^-?([1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0)$

字符表达式

  1. 汉字:^[\u4e00-\u9fa5]{0,}$
  2. 英文和数字:^[A-Za-z0-9]+$^[A-Za-z0-9]{4,40}$
  3. 长度为3-20的所有字符:^.{3,20}$
  4. 由26个英文字母组成的字符串:^[A-Za-z]+$
  5. 由26个大写英文字母组成的字符串:^[A-Z]+$
  6. 由26个小写英文字母组成的字符串:^[a-z]+$
  7. 由数字和26个英文字母组成的字符串:^[A-Za-z0-9]+$
  8. 由数字、26个英文字母或者下划线组成的字符串:^\w+$ 或 ^\w{3,20}$
  9. 中文、英文、数字包括下划线:^[\u4E00-\u9FA5A-Za-z0-9_]+$
  10. 中文、英文、数字但不包括下划线等符号:^[\u4E00-\u9FA5A-Za-z0-9]+$^[\u4E00-\u9FA5A-Za-z0-9]{2,20}$
  11. 可以输入含有^%&amp;',;=?$\"等字符:[^%&amp;',;=?$\x22]+
  12. 禁止输入含有的字符:`[^\x22]+`

特殊需求表达式

  1. Email地址:^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$
  2. 域名:[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(/.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+/.?
  3. InternetURL:[a-zA-z]+://[^\s]* 或 ^http://([\w-]+\.)+[\w-]+(/[\w-./?%&amp;=]*)?$
  4. 手机号码:^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{8}$
  5. 电话号码(“XXX-XXXXXXX”、”XXXX-XXXXXXXX”、”XXX-XXXXXXX”、”XXX-XXXXXXXX”、”XXXXXXX”和”XXXXXXXX):^(\(\d{3,4}-)|\d{3.4}-)?\d{7,8}$
  6. 国内电话号码(0511-4405222、021-87888822):\d{3}-\d{8}|\d{4}-\d{7}
  7. 身份证号(15位、18位数字):^\d{15}|\d{18}$
  8. 短身份证号码(数字、字母x结尾):^([0-9]){7,18}(x|X)?$^\d{8,18}|[0-9x]{8,18}|[0-9X]{8,18}?$
  9. 帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线):^[a-zA-Z][a-zA-Z0-9_]{4,15}$
  10. 密码(以字母开头,长度在6~18之间,只能包含字母、数字和下划线):^[a-zA-Z]\w{5,17}$
  11. 强密码(必须包含大小写字母和数字的组合,不能使用特殊字符,长度在8-10之间):^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,10}$
  12. 日期格式:^\d{4}-\d{1,2}-\d{1,2}
  13. 一年的12个月(01~09和1~12):^(0?[1-9]|1[0-2])$
  14. 一个月的31天(01~09和1~31):^((0?[1-9])|((1|2)[0-9])|30|31)$
  15. 有四种钱的表示形式我们可以接受:”10000.00” 和 “10,000.00”, 和没有 “分” 的 “10000” 和 “10,000”:^[1-9][0-9]*$
  16. 这表示任意一个不以0开头的数字,但是,这也意味着一个字符”0”不通过,所以我们采用下面的形式:^(0|[1-9][0-9]*)$
  17. 一个0或者一个不以0开头的数字.我们还可以允许开头有一个负号:^(0|-?[1-9][0-9]*)$
  18. 这表示一个0或者一个可能为负的开头不为0的数字.让用户以0开头好了.把负号的也去掉,因为钱总不能是负的吧.下面我们要加的是说明可能的小数部分:^[0-9]+(.[0-9]+)?$
  19. 必须说明的是,小数点后面至少应该有1位数,所以”10.”是不通过的,但是 “10” 和 “10.2” 是通过的:^[0-9]+(.[0-9]{2})?$
  20. 这样我们规定小数点后面必须有两位,如果你认为太苛刻了,可以这样:^[0-9]+(.[0-9]{1,2})?$
  21. 这样就允许用户只写一位小数.下面我们该考虑数字中的逗号了,我们可以这样:^[0-9]{1,3}(,[0-9]{3})*(.[0-9]{1,2})?$
  22. 1到3个数字,后面跟着任意个 逗号+3个数字,逗号成为可选,而不是必须:^([0-9]+|[0-9]{1,3}(,[0-9]{3})*)(.[0-9]{1,2})?$
  23. xml文件:^([a-zA-Z]+-?)+[a-zA-Z0-9]+\\.[x|X][m|M][l|L]$
  24. 中文字符的正则表达式:[\u4e00-\u9fa5]
  25. 双字节字符:[^\x00-\xff] (包括汉字在内,可以用来计算字符串的长度(一个双字节字符长度计2,ASCII字符计1))
  26. 空白行的正则表达式:\n\s*\r (可以用来删除空白行)
  27. HTML标记的正则表达式:<(\S*?)[^>]*>.*?</\1>|<.*? />
  28. 首尾空白字符的正则表达式:^\s*|\s*$或(^\s*)|(\s*$) (可以用来删除行首行尾的空白字符(包括空格、制表符、换页符等等),非常有用的表达式)
  29. 腾讯QQ号:[1-9][0-9]{4,} (腾讯QQ号从10000开始)
  30. 中国邮政编码:[1-9]\d{5}(?!\d) (中国邮政编码为6位数字)
  31. IP地址:\d+\.\d+\.\d+\.\d+ (提取IP地址时有用)
  32. IP地址:((?:(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d)\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d))

工具

推荐一款功能十分强大的网页版正则表达式编辑器