您的位置:首页 > 其它

正则表达式全部符号解释及55分钟学…

2017-04-17 15:01 190 查看
字符描述
\将下一个字符标记为一个特殊字符、或一个原义字符、或一个
向后引用、或一个八进制转义符。例如,'n' 匹配字符 "n"。'\n' 匹配一个换行符。序列 '\\' 匹配 "" 而 "\("
则匹配 "("。
^匹配输入字符串的开始位置。如果设置了 RegExp 对象的 Multiline
属性,^ 也匹配 '\n' 或 '\r' 之后的位置。
$匹配输入字符串的结束位置。如果设置了RegExp 对象的 Multiline
属性,$ 也匹配 '\n' 或 '\r' 之前的位置。
*匹配前面的子表达式零次或多次。例如,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?'。请注意在逗号和两个数之间不能有空格。
?当该字符紧跟在任何一个其他限制符 (*, +, ?, {n}, {n,},
{n,m})
后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串
"oooo",'o+?' 将匹配单个 "o",而 'o+' 将匹配所有 'o'。
.匹配除 "\n" 之外的任何单个字符。要匹配包括 '\n'
在内的任何字符,请使用象 '[.\n]' 的模式。
(pattern)匹配 pattern 并获取这一匹配。所获取的匹配可以从产生的 Matches
集合得到,在VBScript 中使用 SubMatches 集合,在JScript 中则使用 $0…$9
属性。要匹配圆括号字符,请使用 '\(' 或 '\)'。
(?:pattern)匹配 pattern
但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。这在使用 "或" 字符 (|)
来组合一个模式的各个部分是很有用。例如, 'industr(?:y|ies) 就是一个比 'industry|industries'
更简略的表达式。
(?=pattern)正向预查,在任何匹配 pattern
的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如,'Windows
(?=95|98|NT|2000)' 能匹配 "Windows 2000" 中的 "Windows" ,但不能匹配 "Windows
3.1" 中的
"Windows"。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。
(?!pattern)负向预查,在任何不匹配 pattern
的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如'Windows
(?!95|98|NT|2000)' 能匹配 "Windows 3.1" 中的 "Windows",但不能匹配 "Windows
2000" 中的
"Windows"。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始
x|y匹配 x 或 y。例如,'z|food' 能匹配 "z" 或
"food"。'(z|f)ood' 则匹配 "zood" 或 "food"。
[xyz]字符集合。匹配所包含的任意一个字符。例如, '[abc]' 可以匹配
"plain" 中的 'a'。
[^xyz]负值字符集合。匹配未包含的任意字符。例如, '[^abc]' 可以匹配
"plain" 中的'p'。
[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_]'。
\xn匹配 n,其中 n
为十六进制转义值。十六进制转义值必须为确定的两个数字长。例如,'\x41' 匹配 "A"。'\x041' 则等价于 '\x04'
& "1"。正则表达式中可以使用 ASCII 编码。.
\num匹配 num,其中 num
是一个正整数。对所获取的匹配的引用。例如,'(.)\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),则匹配八进制转义值 nml。
\un匹配 n,其中 n 是一个用四个十六进制数字表示的 Unicode
字符。例如, \u00A9 匹配版权符号 (?)。
原文链接:http://www.cnblogs.com/yirlin/archive/2006/04/12/373222.html

55分钟学习正则表达式

在用R处理网页抓取的数据的时候,总是会涉及到正则表达式,看到一篇不错的介绍转载如下
正则表达式是一种查找以及字符串替换操作。正则表达式在文本编辑器中广泛使用,比如正则表达式被用于:

检查文本中是否含有指定的特征词

找出文中匹配特征词的位置

从文本中提取信息,比如:字符串的子串

修改文本

与文本编辑器相似,几乎所有的高级编程语言都支持正则表达式。在这样的语境下,“文本”也就是一个字符串,可以执行的操作都是类似的。一些编程语言(比如Perl,JavaScript)会检查正则表达式的语法。
正则表达式是什么?
正则表达式只是一个字符串。没有长度限制,但是,这样的正则表达式长度往往较短。如下所示是一些正则表达式的例子:

I had a S+ day
today

[A-Za-z0-9-_]{3,16}

dddd-dd-dd

v(d+)(.d+)*

TotalMessages="(.*?)"

<[^<>]>

这些字符串实际上都是微型计算机程序。正则表达式的语法,实际上是一种轻量级、简洁、适用于特定领域的编程语言。记住这一点,那么你就很容易理解下面的事情:

每一个正则表达式,都可以分解为一个指令序列,比如“先找到这样的字符,再找到那样的字符,再从中找到一个字符。。。”

每一个正则表达式都有输入(文本)和输出(匹配规则的输出,有时是修改后的文本)

正则表达式有可能出现语法错误——不是所有的字符串都是正则表达式

正则表达式语法很有个性,也可以说很恐怖

有时可以通过编译,使得正则表达式执行更快

在实现中,正则表达式还有其他的特点。本文将重点讨论正则表达式的核心语法,在几乎所有的正则表达式中都可以见到这些规则。
特别提示:正则表达式与文件通配语法无关,比如 *.xml
正则表达式的基础语法字符
正则表达式中包含了一系列的字符,这些字符只能匹配它们本身。有一些被称为“元字符”的特殊字符,可以匹配一些特殊规则。
如下所示的例子中,我用红色标出了元字符。

I had a S+ day
today

[A-Za-z0-9-_]{3,16}

dddd-dd-dd

v(d+)(.d+)*

TotalMessages="(.*?)"

<[^<>]*>

大部分的字符,包括所有的字母和数字字符,是普通字符。也就意味着,它们只能匹配它们自己,如下所示的正则表达式:

cat
意味着,只能匹配一个字符串,以“c”开头,然后是字符“a”,紧跟着是字符“t”的字符串。
到目前为止,正则表达式的功能类似于

常规的Find功能

Java中的 String.indexOf()
函数

PHP中的 strpos()函数

等等

注意:不做特殊说明,正则表达式中是区分大小写的。但是,几乎所有正则表达式的实现,都会提供一个Flag用来控制是否区分大小写。
点“.”我们第一个要讲解的元字符是“.”。这个符号意味着可以匹配任意一个字符。如下所示的正则表达式:

c.t
意味着匹配“以c开头,之后是任意一个字符,紧跟着是字母t”的字符串。
在一段文本中,这样的正则表达式可以用来找出cat, cot,
czt这样的字符串,甚至可以找出c.t这样的组合,但是不能找到ct或者是coot这样的字符串。
使用反斜杠“”可以忽略元字符,使得元字符的功能与普通字符一样。所以,正则表达式

c.t
表示“找到字母c,然后是一个句号(“.”),紧跟着字母t”
反斜杠本身也是一个元字符,这意味着反斜杠本身也可以通过相似的方法变回到普通字符的用途。因此,正则表达式

c\t
表示匹配“以字符c开头,然后是一个反斜杠,紧跟着是字母t”的字符串。
注意!在正则表达式的实现中,.是不能用于匹配换行符的。”换行符“的表示方法在不同实现中也不同。实际编程时,请参考相关文档。在本文中,我认为.是可以匹配任意字符的。实现环境通常会提供一个Flag标志位,来控制这一点。

字符类字符类是一组在方括号内的字符,表示可以匹配其中的任何一个字符。

正则表达式c[aeiou]t,表示可以匹配的字符串是”以c开头,接着是aeiou中的任何一个字符,最后以t结尾”。在文本的实际应用中,这样的正则表达式可以匹配:cat,cet,cit,cot,cut五种字符串。

正则表达式[0123456789]表示匹配任意一个整数。

正则表达式[a]表示匹配单字符a。

包含忽略字符的例子

a

表示匹配字符串[a]

[[]ab]表示匹配的字符为”["或者'']”或者”a”,或者”b”

[\[]]表示匹配的字符为””或者
“[”或者"]“

在字符类中,字符的重复和出现顺序并不重要。[dabaaabcc]与[abc]是相同的

重要提示:字符类中和字符类外的规则有时不同,一些字符在字符类中是元字符,在字符类外是普通字符。一些字符正好相反。还有一些字符在字符类中和字符类外都是元字符,这要视情况而定!

比如,.表示匹配任意一个字符,而[.]表示匹配一个全角句号。这不是一回事!

字符类的范围在字符集中,你可以通过使用短横线来表示匹配字母或数字的范围。

[b-f]与[b,c,d,e,f]相同,都是匹配一个字符”b”或”c”或”d”或”e”或”f”

[A-Z]与[ABCDEFGHIJKLMNOPQRSTUVWXYZ]相同,都是匹配任意一个大写字母。

[1-9]与[123456789]相同,都是匹配任意一个非零数字。

练习使用目前我们已经讲解的正则表达式相关知识,在字典中匹配找到含有最多连续元音的单词,同时找到含有最多连续辅音的单词。

答案[aeiou][aeiou][aeiou][aeiou][aeiou][aeiou]
这样的正则表达式,可以匹配连续含有六个元音的单词,比如 euouae 和 euouaes。
同样的,恐怖的正则表达式[bcdfghjklmnpqrstvwxyz][bcdfghjklmnpqrstvwxyz][bcdfghjklmnpqrstvwxyz][bcdfghjklmnpqrstvwxyz][bcdfghjklmnpqrstvwxyz][bcdfghjklmnpqrstvwxyz][bcdfghjklmnpqrstvwxyz][bcdfghjklmnpqrstvwxyz][bcdfghjklmnpqrstvwxyz][bcdfghjklmnpqrstvwxyz]
可以找到连续含有十个辅音的单词sulphhydryls.
下文中,我们会讲解,怎样有效缩短这样的正则表达式长度。

在字符类之外,短横线没有特殊含义。正则表达式a-z,表示匹配字符串“以a开头,然后是一个短横线,以z结尾”。

范围和单独的字符可能在一个字符类中同时出现:

[0-9.,]表明匹配一个数字,或者一个全角句号,或者一个逗号

[0-9a-fA-F]意味着匹配一个十六进制数

[a-zA-Z0-9-]意味着匹配一个字母、数字或者一个短横线

练习使用已经介绍过的正则表达式知识,匹配YYYY-MM-DD格式的日期。

答案[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9].

同样的,下文中,我们会介绍怎样有效减少这样的正则表达式长度。

虽然你可以尝试在正则表达式中使用一些非字母或数字作为范围的最后一个符号,比如abc[!-/]def,但是这并不是在每种实现中都合法。即使这样的语法是合法的,这样的语义也是模糊的。最好不要这样使用。

同时,你必须谨慎选择范围的边界值。即使[A-z]在你使用的实现中,是合法的,也可能会产生无法预料的运行结果。(注意,在z到a之间,是有字符存在的)

注意:范围的字符值代表的是字符而已,并不能代表数值范围,比如[1-31]表示匹配一个数字,是1或者2或者3,而不是匹配一个数值在1到31之间的数。

字符类的反义你可以在字符类的起始位放一个反义符。

[^a]表示匹配任何不是“a”的字符

[^a-zA-Z0-9]表示匹配任何不是字母也不是数字的字符

[^abc]匹配一个为“^”或者a或者b或者c的字符

[^^]表示匹配任何不为“^”的字符

练习在字典中,找到一个不满足“在e之前有i,但是没有c”的例子。

答案

cie和[^c]ei都要可以找到很多这样的例子,比如ancient,science,viel,weigh

转义字符类d这个正则表达式与[0-9]作用相同,都是匹配任何一个数字。(要匹配d,应该使用正则表达式\d)

w与[0-9A-Za-z]相同,都表示匹配一个数字或字母字符

s意味着匹配一个空字符(空格,制表符,回车或者换行)

另外

D与[^0-9]相同,表示匹配一个非数字字符。

W与[^0-9A-Za-z]相同,表示匹配一个非数字同时不是字母的字符。

S表示匹配一个非空字符。

这些是你必须掌握的字符。你可能已经注意到了,一个全角句号“.”也是一个字符类,可以匹配任意一个字符。

很多正则表达式的实现中,提供了更多的字符类,或者是标志位在ASCII码的基础上,扩展现有的字符类。

特别提示:统一字符集中包含除了0至9之外的更多数字字符,同样的,也包含更多的空字符和字母字符。实际使用正则表达式时,请仔细查看相关文档。

练习简化正则表达式 [0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9].

答案dddd-dd-dd.

重复在字符或字符集之后,你可以使用{ }大括号来表示重复

正则表达式a{1}与a意思相同,都表示匹配字母a

a{3}表示匹配字符串“aaa”

a{0}表示匹配空字符串。从这个正则表达式本身来看,它毫无意义。如果你对任何文本执行这样的正则表达式,你可以定位到搜索的起始位置,即使文本为空。

a{2}表示匹配字符串“a{2}”

在字符类中,大括号没有特殊含义。[{}]表示匹配一个左边的大括号,或者一个右边的大括号

练习简化下面的正则表达式

z.......z

dddd-dd-dd

[aeiou][aeiou][aeiou][aeiou][aeiou][aeiou]

[bcdfghjklmnpqrstvwxyz][bcdfghjklmnpqrstvwxyz][bcdfghjklmnpqrstvwxyz][bcdfghjklmnpqrstvwxyz][bcdfghjklmnpqrstvwxyz][bcdfghjklmnpqrstvwxyz][bcdfghjklmnpqrstvwxyz][bcdfghjklmnpqrstvwxyz][bcdfghjklmnpqrstvwxyz][bcdfghjklmnpqrstvwxyz]

答案
z.{7}z

d{4}-d{2}-d{2}

[aeiou]{6}

[bcdfghjklmnpqrstvwxyz]{10}

注意:重复字符是没有记忆性的,比如[abc]{2}表示先匹配”a或者b或者c”,再匹配”a或者b或者c”,与匹配”aa或者ab或者ac或者ba或者bb或者bc或者ca或者cb或者cc“一样。[abc]{2}并不能表示匹配”aa或者bb或者cc“

指定重复次数范围重复次数是可以指定范围的

x{4,4}与x{4}相同

colou{0,1}r表示匹配colour或者color

a{3,5}表示匹配aaaaa或者aaaa或者aaa

注意这样的正则表达式会优先匹配最长字符串,比如输入 I had an
aaaaawful day会匹配单词aaaaawful中的aaaaa,而不会匹配其中的aaa。
重复次数是可以有范围的,但是有时候这样的方法也不能找到最佳答案。如果你的输入文本是I
had an aaawful daaaaay那么在第一次匹配时,只能找到aaawful,只有再次执行匹配时才能找到daaaaay中的aaaaa.

重复次数的范围可以是开区间

a{1,}表示匹配一个或一个以上的连续字符a。依然是匹配最长字符串。当找到第一个a之后,正则表达式会尝试匹配尽量多个的连续字母a。

.{0,}表示匹配任意内容。无论你输入的文本是什么,即使是一个空字符串,这个正则表达式都会成功匹配全文并返回结果。

练习使用正则表达式找到双引号。要求输入字符串可能包含任意个字符。

调整你的正则表达式使得在一对双引号中间不再包含其他的双引号。

答案 ".{0,}", 然后 "[^"]{0,}".

关于重复的转义字符?与{0,1}相同,比如,colou?r表示匹配colour或者color

*与{0,}相同。比如,.*表示匹配任意内容

+与{1,}相同。比如,w+表示匹配一个词。其中”一个词”表示由一个或一个以上的字符组成的字符串,比如_var或者AccountName1.

这些是你必须知道的常用转义字符,除此之外还有:

?*+
表示匹配字符串”?*+”

[?*+]表示匹配一个问号,或者一个*号,或者一个加号

练习简化下列的正则表达式:

".{0,}" and
"[^"]{0,}"

x?x?x?

y*y*

z+z+z+z+

答案
".*" and
"[^"]*"

x{0,3}

y*

z{4,}

练习写出正则表达式,寻找由非字母字符分隔的两个单词。如果是三个呢?六个呢?

w+W+w+, w+W+w+W+w+, w+W+w+W+w+W+w+W+w+W+w+.

下文中,我们将简化这个正则表达式。

非贪婪匹配正则表达式 “.*”
表示匹配双引号,之后是任意内容,之后再匹配一个双引号。注意,其中匹配任意内容也可以是双引号。通常情况下,这并不是很有用。通过在句尾加上一个问号,可以使得字符串重复不再匹配最长字符。

d{4,5}?表示匹配dddd或者ddddd。也就是和d{4}一样

colou??r与colou{0,1}r相同,表示找到color或者colour。这与colou?r一样。

“.*?”表示先匹配一个双引号,然后匹配最少的字符,然后是一个双引号,与上面两个例子不同,这很有用。

选择匹配你可以使用|来分隔可以匹配的不同选择:

cat|dog表示匹配”cat”或者”dog”

red|blue|以及red||blue以及|red|blue都表示匹配red或者blue或者一个空字符串

a|b|c与[abc]相同

cat|dog||表示匹配”cat”或者”dog”或者一个分隔符”|“

[cat|dog]表示匹配a或者c或者d或者g或者o或者t或者一个分隔符“|”

练习简化下列正则表达式:

s|t|u|v|w

aa|ab|ba|bb

[abc]|[^abc]

[^ab]|[^bc]

[ab][ab][ab]?[ab]?

答案

[s-w]

[ab]{2}

.

[^b]

[ab]{2,4}

练习使用正则表达式匹配1到31之间的整数,[1-31]不是正确答案!

这样的正则表达式不唯一. [1-9]|[12][0-9]|3[01] 是其中之一。

分组你可以使用括号表示分组:

通过使用 Mon|Tues|Wednes|Thurs|Fri|Satur|Sun)day
匹配一周中的某一天

(w*)ility 与 w*ility 相同。都是匹配一个由”ility”结尾的单词。稍后我们会讲解,为何第一种方法更加有用。

表示匹配一对括号。

[()]表示匹配任意一个左括号或者一个右括号

练习在《时间机器中》找到一对括号中的内容,然后通过修改正则表达式,找到不含括号的内容。

答案.∗. 然后是, [()]∗.

分组可以包括空字符串:

(red|blue)表示匹配red或者blue或者是一个空字符串

abc()def与abcdef相同

你也可以在分组的基础上使用重复:

(red|blue)?与(red|blue|)相同

w+(s+w+)表示匹配一个或多个由空格分隔的单词

练习简化正则表达式 w+W+w+W+w+ 以及
w+W+w+W+w+W+w+W+w+W+w+.

答案w+(W+w+){2}, w+(W+w+){5}.

单词分隔符在单词和非单词之间有单词分隔符。记住,一个单词w是[0-9A-Za-z_],而非单词字符是W(大写),表示[^0-9A-Za-z_].

在文本的开头和结尾通常也有单词分隔符。

在输入文本it’s a
cat中,实际有八个单词分隔符。如果我们在cat之后在上一个空格,那就有九个单词分隔符。.

b表示匹配一个单词分隔符

bwwwb表示匹配一个三字母单词

aba表示匹配两个a中间有一个单词分隔符。这个正则表达式永远不会有匹配的字符,无论输入怎样的文本。

单词分隔符本身并不是字符。它们的宽度为0。下列正则表达式的作用不同

(bcat)b

(bcatb)

b(cat)b

b(catb)

练习在词典中找到最长的单词。

答案在尝试之后发现,b.{45,}b可以在字典中找到最长单词

换行符一篇文本中可以有一行或多行,行与行之间由换行符分隔,比如:

Line一行文字

Line break换行符

Line一行文字

Line break换行符



Line break换行符

Line一行文字

注意,所有的文本都是以一行结束的,而不是以换行符结束。但是,任意一行都可能为空,包括最后一行。

行的起始位置,是在换行符和下一行首字符之间的空间。考虑到单词分隔符,文本的起始位置也可以当做是首行位置。

最后一行是最后一行的尾字符和换行符之间的空间。考虑到单词分隔符,文本的结束也可以认为是行的结束。

那么新的格式表示如下:

Start-of-line, line,
end-of-line

Line break

Start-of-line, line,
end-of-line

Line break



Line break

Start-of-line, line,
end-of-line

基于上述概念:

^表示匹配行的开始位置

$表示匹配行的结束位置

^&表示一个空行

^.*& 表示匹配全文内容,因为行的开始符号也是一个字符,"."会匹配这个符号。找到单独的一行,可以使用
^.*?$

^表示匹配字符串“^"
style="position: relative;" tabindex="0"
id="MathJax-Element-1-Frame" class="MathJax">表示匹配字符串“^



[]表示匹配一个"
style="position: relative;" tabindex="0"
id="MathJax-Element-2-Frame" class="MathJax">

表示匹配一个 

。但是,[^]不是合法的正则表达式。记住在方括号中,字符有不同的特殊含义。要想在方括号内匹配^,必须用[^]

与字符分隔符一样,换行符也不是字符。它们宽度为0.如下所示的正则表达式作用不同:

(^cat)$

(^cat$)

^(cat)$

^(cat$)

练习使用正则表达式在《时间机器》中找到最长的一行。

答案使用正则表达式^.{73,}可以匹配长度为73的一行文本分界在很多的正则表达式实现中,将和"
style="position: relative;" tabindex="0"
id="MathJax-Element-3-Frame" class="MathJax">可以匹配长度为



的一行文本分界在很多的正则表达式实现中,将 和  作为文本的开始符号和结束符号。

还有一些实现中,用A和z作为文本的开始和结束符号。

捕捉和替换从这里开始,正则表达式真正体现出了它的强大。

捕获组你已经知道了使用括号可以匹配一组符号。使用括号也可以捕获子串。假设正则表达式是一个小型计算机程序,那么捕获子串就是它输出的一部分。

正则表达式(w*)ility表示匹配以ility结尾的词。第一个被捕获的部分是由w*控制的。比如,输入的文本内容中有单词accessibility,那么首先被捕获的部分是accessib。如果输入的文本中有单独的ility,则首先被捕获的是一个空字符串。

你可能会有很多的捕获字符串,它们可能靠得很近。捕获组从左向右编号。也就是只需要对左括号计数。

假设有这样的正则表达式:(w+) had a ((w+) w+)
输入的内容是:I had a
nice day

捕获组1:I

捕获组2:nice day

捕获组3:nice

在一些正则表达式的实现中,你可以从零开始编号,编号零表示匹配整句话:I had a
nice day.

在其他的实现中,如果没有制定捕获组,那么捕获组1会自动地填入捕获组0的信息。

是的,这也意味着会有很多的括号。有一些正则表达式的实现中,提供了“非捕获组”的语法,但是这样的语法并不是标准语法,因此我们不会介绍。

从一个成功的匹配中返回的捕获组个数,与使用原来的正则表达式获得的捕获组个数相同。记住这一点,你可以解释一些奇怪的现象。.

正则表达式((cat)|dog)表示匹配cat或者dog。这里有两个捕获组,如果输入文本是dog,那么捕获组1是dog,捕获组2为空。

正则表达式a(w)*表示匹配一个以a开头的单词。这里只有一个捕获组

如果输入文本为a,捕获组1为空。

如果输入文本为ad,捕获组为d

如果输入文本为avocado,捕获组1为v。但是捕获组0表示整个单词avocado.

替换假如你使用了一个正则表达式去匹配字符串,你可以描述另外一个字符串来替换其中的匹配字符。用来替换的字符串称为替换表达式。它的功能类似于

常规的Replace会话

Java中的String.replace()函数

PHP的str_replace()函数

等等

练习将《时间机器》中所有的元音字母替换为r。

答案使用正则表达式[aeiou]以及[AEIOU],对应的替换字符串分别为r,R.

但是,你可以在替换表达式中引用捕获组。这是在替换表达式中,你可以唯一操作的地方。这也是非常有效的,因为这样你就不用重构你找到的字符串。

假设你正在尝试将美国风格的日期表示MM/DD/YY替换为ISO 8601日期表示YYYY-MM-DD

从正则表达式(dd)/(dd)/(dd)开始。注意,这其中有三个捕获组:月份,日期和两位的年份。

.捕获组的内容和捕获组编号之间用反斜杠分隔,因此你的替换表达式应该是203-1-2.

如果我们输入的文本中包含03/04/05表示2005年3月4日那么:

捕获组1:03

捕获组2:04

捕获组3:05

替换字符串2005-03-04.

在替换表达式中,你可以多次使用捕获组

对于双元音,正则表达式为([aeiou]),替换表达式为ll

在替换表达式中不能使用反斜杠。比如,你在计算机程序中希望使用字符串中使用部分文本。那么,你必须在每个双引号或者反斜杠之前加上反斜杠。

你的正则表达式可以是(["])。捕获组1是双引号或者反斜杠

你的替换表达式应该是\l

在某些实现中,采用美元符号$代替

练习使用正则表达式和替换表达式,将23h59这样的时间戳转化为23:59.

答案正则表达式finds the timestamps, 替换表达式1:2

反向引用在一个正则表达式中,你也可以引用捕获组。这称作:反向引用

比如,[abc]{2}表示匹配aa或者ab或者ac或者ba或者bb或者bc或者ca或者cb或者cc.但是{[abc]}1表示只匹配aa或者bb或者cc.

练习在字典中,找到包含两次重复子串的最长单词,比如papa, coco

b(.{6,})1b 匹配 chiquichiqui.
如果我们不在乎单词的完整性,我们可以忽略单词的分解,使用正则表达式
(.{7,})1匹配countercountermeasure 以及
countercountermeasures.

使用正则表达式编程特别提醒:

过度使用的反斜杠在一些编程语言,比如Java中,对于包含正则表达式的字符串没有特殊标记。字符串有着自己的过滤规则,这是优先于正则表达式规则的,这是频繁使用反斜杠的原因。

比如在Java中

匹配一个数字,使用的正则表达式从d变为代码中的String re=
“\d”

匹配双引号字符串的正则表达式从"[^"]*"
变为String re = “”[^"]*”"

匹配反斜杠或者是左边方括号,或者右边方括号的正则表达式从[\[]] 变为String re = “[\\

]”;

String re = "\s"; 和String
re = "[ trn]"; 是等价的. 注意它们实际执行调用时的层次不同。

在其他的编程语言中,正则表达式是由特殊标明的,比如使用/。下面是JavaScript的例子:

匹配一个数字,d会简单写成 var regExp =
/d/;.

匹配一个反斜杠或者一个左边的方括号或者一个右边的方括号, var regExp =
/[\[]]/;

var regExp = /s/; 和 var
regExp = /[ trn]/; 是等价的

当然,这意味着在使用/时必须重复两次。比如找到URL必须使用var regExp =
/https?:///;.

我希望现在你能明白,我为什么让你特别注意反斜杠。

动态正则表达式当你动态创建一个正则表达式的时候请特别小心。如果你使用的字符串不够完善的花,可能会有意想不到的匹配结果。这可能导致语法错误,更糟糕的是,你的正则表达式语法正确,但是结果无法预料。

错误的Java代码:

String sep = System.getProperty(“file.separator”); String[]
directories = filePath.split(sep);
Bug:String.split() 认为sep是一个正则表达式。但是,在Windows中,Sep是表示匹配一个反斜杠,也就是与正则表达式”\”相同。这个正则表达式是正确的,但是会返回一个异常:PatternSyntaxException.

任何好的编程语言都会提供一种良好的机制来跳过字符串中所有的元字符。在Java中,你可以这样实现:

String sep = System.getProperty(“file.separator”);

String[] directories = filePath.split(Pattern.quote(sep));

循环中的正则表达式将正则表达式字符串加入反复运行的程序中,是一种开销很大的操作。如果你可以在循环中避免使用正则表达式,你可以大大提高效率。

其他建议输入验证正则表达式可以用来进行输入验证。但是严格的输入验证会使得用户体验较差。比如:

信用卡号在一个网站上,我输入了我的卡号比如 1234 5678 8765 4321
网站拒绝接收。因为它使用了正则表达式d{16}。
正则表达式应该考虑到用户输入的空格和短横线。

实际上,为什么不先过滤掉所有的非数字字符,然后再进行有效性验证呢?这样做,可以先使用D以及空的替换表达式。

练习在不先过滤掉所有的非数字字符的情况下,使用正则表达式验证卡号的正确性。

答案D*(dD*){16} is one of several variations which would accomplish
this.

名字不要使用正则表达式来验证姓名。实际上,即使可以,也不要企图验证姓名。

程序员对名字的错误看法:

名字中不含空格

名字中没有连接符号

名字中只会使用ASCII码字符

名字中出现的字都在特殊字符集中

名字至少要有M个字的长度

名字不会超过N个字的长度

人们只有一个名

人们只有一个中间名

人们只有一个姓(最后三条是从英语的人名考虑)

电子邮件地址不要使用正则表达式验证邮箱地址的正确性。

首先,这样的验证很难是精确的。电子邮件地址是可以用正则表达式验证的,但是表达式会非常的长并且复杂。

短的正则表达式会导致错误。(你知道吗?电子邮箱地址中会有一些注释)

第二,即使一个电子邮件地址可以成功匹配正则表达式,也不代表这个邮箱实际存在。邮箱的唯一验证方法,是发送验证邮件。

注意在严格的应用场景中,不要使用正则表达式来解析HTML或者XML。解析HTML或者XML:

使用简单的正则表达式不能完成

总体来说非常困难

已经有其他的方法解决

找到一个已经有的解析库来完成这个工作

这就是55分钟的全部内容总结:

字符: a b c d 1 2 3 4
etc.

字符类: . [abc] [a-z] d w
s

. 代表任何字符

d 表示“数字”


 表示”字母”, [0-9A-Za-z_]


 表示 “空格, 制表符,回车或换行符”

否定字符类: [^abc] D W
S

重复: {4} {3,16} {1,} ? *
+

? 表示 “零次或一次”

* 表示 “大于零次”

+ 表示 “一次或一次以上”

如果不加上?,所有的重复都是最长匹配的(贪婪)

分组:
(Septem|Octo|Novem|Decem)ber

词,行以及文本的分隔: b ^ $ A
z

转义字符: 1 2 3 etc.
(在匹配表达式和替换表达式中都可用)

元字符:
.  [ ] { } ? * + | ( ) ^
$

在字符类中使用元字符: [
]  - ^

使用反斜杠可以忽略元字符:

致谢正则表达式非常常用而且非常有用。每个人在编辑文本或是编写程序时都必须了解怎样使用正则表达式。

练习选择正则表达式的某种实现,阅读相关文档。我保证,你会学到更多。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: