正则表达式详解

正则表达式详解
正则表达式详解

正则表达式

1.什么是正则表达式

简单的说,正则表达式是一种可以用于文字模式匹配和替换的强有力的工具。是由一系列普通字符和特殊字符组成的能明确描述文本字符串的文字匹配模式。

正则表达式并非一门专用语言,但也可以看作是一种语言,它可以让用户通过使用一系列普通字符和特殊字符构建能明确描述文本字符串的匹配模式。除了简单描述这些模式之外,正则表达式解释引擎通常可用于遍历匹配,并使用模式作为分隔符来将字符串解析为子字符串,或以智能方式替换文本或重新设置文本格式。正则表达式为解决与文本处理有关的许多常见任务提供了有效而简捷的方式。

正则表达式具有两种标准:

·基本的正则表达式(BRE –Basic Regular Expressions)

·扩展的正则表达式(ERE – Extended Regular Expressions)。

ERE包括BRE功能和另外其它的概念。

正则表达式目前有两种解释引擎:

·基于字符驱动(text-directed engine)

·基于正则表达式驱动(regex-directed engine)

Jeffery Friedl把它们称作DFA和NFA解释引擎。

约定:

为了描述起来方便,在本文中做一些约定:

1.本文所举例的所有表达时都是基于NFA解释引擎的。

2.正则表达式,也就是匹配模式,会简写为Regex。

3. Regex的匹配目标,也就是目标字符串,会简写为String。

4.匹配结果用会用黄色底色标识。

5.用1\+1=2 括起来的表示这是一个regex。

6.举例会用以下格式:

test

This is a test

会匹配test,testcase等

2.正则表达式的起源

正则表达式的”祖先”可以一直上溯至对人类神经系统如何工作的早期研究。Warren McCulloch 和 Walter Pitts 这两位神经生理学家研究出一种数学方式来描述这些神经网络。

1956 年, 一位叫 Stephen Kleene 的美国数学家在 McCulloch 和 Pitts 早期工作的基础上,发表了一篇标题为”神经网事件的表示法”的论文,引入了正则表达式的概念。正则表达式就是用来描述他称为”正则集的代数”的表达式,因此采用”正则表达式”这个术语。

随后,发现可以将这一工作应用于使用Ken Thompson 的计算搜索算法的一些早期研究,Ken Thompson是Unix 的主要发明人。正则表达式的第一个实用应用程序就是 Unix 中的qed 编辑器。从那时起直至现在正则表达式都是基于文本的编辑器和搜索工具中的一个重要部分。具有完整语法的正则表达式使用在字符的格式匹配方面上,后来被应用到熔融信息技术领域。自从那时起,正则表达式经过几个时期的发展,现在的标准已经被ISO(国际标准组织)批准和被Open Group组织认定。

3. 正则表达式使用详解

最简单的正则表达式相信大家都已熟悉并且经常使用,那就是文字字符串。特定的字符串可

通过文字本身加以描述;像 test这样的Regex模式可精确匹配输入的字符串”test”,但是它也可以匹配this is a testcase,这就不是我们想要得结果。

当然,使用正则表达式匹配等于它自身的精确字符串是没有价值的实现,不能体现正则表达式的真正作用。但是,假如要查找的不是test,而是所有以字母 t 开头的单词,或所有4个字母的单词,那该怎么办?这超出了文字字符串的合理范围。所以我们才需要深入地研究正则表达式。

3.1基本语法

虽然正则表达式并非一门专用语言,但它也有一些特殊的规定,也可以称之为基本语法。

正则表达式是由普通字符(例如字符 a 到z)以及特殊字符(称为元字符)组成的文字模式。该模式描述在查找文字主体时待匹配的一个或多个字符串。正则表达式作为一个模板,将某个字符模式与所搜索的字符串进行匹配。

构造正则表达式的方法和创建数学表达式的方法一样。也就是用多种元字符与操作符将小的表达式结合在一起来创建更大的表达式。

可以通过在一对分隔符之间放入表达式模式的各种组件来构造一个正则表达式。

3.1.1普通字符

由所有那些未显式指定为元字符的打印和非打印字符组成。这包括所有的大写和小写字母字符,所有数字,所有标点符号以及一些符号。

3.1.2非打印字符

非打印字符也是普通字符,单独列出来便于参考。

非打印字符参考(有错大家矫正,JS手册都有)

\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。

Regex中可以使用非打印字符。\t会匹配一个tab字符(ASC||),\r 会匹配一个回车(0x0D),\n 会匹配一个换行符(0x0A)。应该注意的是:Windows使用\r\n表示一行的结束,而UNIX使用\n 。同样,我们可以在Regex中使用16进制的ASCⅡ码或者ANSI标准码。在拉丁语中,版权符号的代码是0xA9,所以我们也可以这样来匹配版权符号 \xA9 。另外一个匹配tab的写法是:\x09 。但是注意,第一位的”0”必须去掉。

3.1.3特殊字符

特殊字符也叫做元字符,保留字符(Metacharactor),在Regex中表示特殊的意义,大部分的意思在不同的上下文中的意义是不同的,这里只列出最普遍的意义。

特殊字符共有11个:

$

匹配输入字符串的结尾位置。如果设置了 RegExp 对象的 Multiline 属性,则 $ 也匹配 '\n' 或 '\r'。要匹配 $ 字符本身,请使用 \$。

( )

标记一个子表达式的开始和结束位置。子表达式可以获取供以后使用。要匹配这些字符,请使用 \( 和 \)。

*

匹配前面的子表达式零次或多次。要匹配 * 字符,请使用 \*。

+

匹配前面的子表达式一次或多次。要匹配 + 字符,请使用 \+。

.

匹配除换行符 \n之外的任何单字符。要匹配.,请使用\。

[

标记一个中括号表达式的开始。要匹配[,请使用 \[。

?

匹配前面的子表达式零次或一次,或指明一个非贪婪限定符。要匹配 ? 字符,请使用 \?。

\

将下一个字符标记为或特殊字符、或原义字符、或反向引用、或八进制转义符。例如, 'n' 匹配字符 'n'。'\n' 匹配换行符。序列 '\\' 匹配 "\",而 '\(' 则匹配 "("。

^

匹配输入字符串的开始位置,除非在方括号表达式中使用,此时它表示不接受该字符集合。要匹配 ^ 字符本身,请使用 \^。

{

标记限定符表达式的开始。要匹配{,请使用 \{。

|

指明两项之间的一个选择。要匹配|,请使用 \|。

在元字符前加 \ 转义符,可以把特殊字符当作普通字符来使用。

比如:如要要匹配 1+1=2 ,正确的正则表达式应该为1\+1=2。否则, + 会被当作特殊字符对待。

除了特殊字符,所有的其他字符都不应该加 \ 。因为 \ 也是一个特殊字符。\ 和普通字符组合在一起也可以创造一种特殊的意义。比如 \d 表示匹配所有的数字。

作为程序员,单引号和双引号不是特殊字符会也许让我们感到很惊讶。但这是正确的。因为我们在编程的时候,编程语言会知道引号之间的哪些字符表示特殊意义,编译器在把字符串x传递给regex解释引擎之前,会把它们处理成regex。比如,在C#中,如果我们要匹配 1\+1=2 ,在程序中我们要这样写: “1\\+1=2” ,C#编译器会把 “\\” ,处理为一个”\” 。同样,如果要匹配C:\Temp ,首先,正则表达式要这样写 C:\\Temp,然后在程序中我们应该这样写:” C:\\\\temp”。

3.1.4字符集

字符集描述了一组字符,Regex解释器会认为匹配字符集中的一个字符就可以认为匹配成功。

字符集用[ ]括起来即可。

比如gr[ae]y就可以匹配gray或者grey。

字符集只能匹配一个字符,gr[ae]y就不能和graey匹配。字符集中的字符顺序是任意的,得到的结果都是唯一的。

可以在字符集中用连字符”-”来表示一个范围。[0-9]的结果和[0123456789]的匹配结果都是相同的。字符集中的范围可以有多种。比如[0-9a-fA-F]表示匹配所有的16进制,包括大小写。也可以把范围和单个字符组合在一起用,[0-9a-fxA-FX]表示匹配所有的16进制或者一个字符X。字符集的顺序不会影响结果。

在字符集的开始标志”[“后面加上一个”^”符号,表示否定,表示匹配除字符集中定义的字符以外的所有字符。包括非打印字符和行结束符。

注意:字符集匹配的一个字符,而不是一个位置。所以。q[^u]的意义不是”q后面的字符不是u”。而是”q后面的字符可以是除了u以外的所有字符”。

q[^u]不会和Iraq匹配。

但是会和Iraq is a country匹配,因为q后面的空格字符是一个”不是u的字符”。

3.1.5在字符集中使用元字符

字符集中的元字符只能是‘]’, ‘\’, ‘^’, 和 ‘-’ 。

其他元字符在字符集中都失去了特殊意义,表示的只是一个普通字符。也不需要用加”\”。

比如:

匹配一个”*”或者”+”,用[*+]就足够了。即使给他们加上”\”,regex解释器也会把他们忽略掉。

四种特殊字符的处理:

在字符集中要表示”]”,”^”和”-”需要在后面加上转义符”\”,来表示它们代表的分别是普通字符”]”,”^”和”-”。

也可以把它们放在一个不能表示特殊意义的位置,后一个方法比较好,因为他们不会影响可读性。

“^”

要想匹配一个”^”,可以把它放在除了紧跟”[“的任意一个位置。

Regex

String

Description

[x^]

A string with x and ^.

匹配x或者”^”

“]”

可以把”]”放在紧跟着”[“的位置,或者使用否定字符集。

Regex

String

Description

[]x]

A string with x and ]

匹配x或者”]”

[^]x]

A string with x and ]

匹配除了x和”] “以外的所有字符

“\”

要想把”\”当作一个普通字符来匹配,而不是一个特殊字符,必须把”\”再用一个”\”括起来。

[\\x]

A string with x and \

匹配x或者”\”

“-”

连字符可以放在紧跟着”[“的后面,或者正好”]”的前面,或者紧跟着”^”的后面。

[-x]

A string with x and -

匹配x或者”-”

[x-]

A string with x and -

匹配x或者”-”

预定义字符集

因为很多字符集是经常使用的,所以Regex解释器预定义了一些常用字符集:

d

[0-9]

所有数字

\w

[a-zA-Z]

表示所有的字符,和文化字体有关

\s

[ \t\r\n]

空格,回车和tab。和文化字体有关

预订一字符集可以既可以用在字符集里面,也可以用在字符集外面。

\s\d

1+2=3

匹配后面紧跟着一个数字的空白符

[\s\d]

1+2=3

匹配一个单独的字符或者一个数字或者一个空白符

[\da-fA-F]和[0-9a-fA-F]的匹配结果是一样的。

同样,在预定义字符集前面加一个”^”符号表示否定。它们也有预先定义好的表示:

\D

[^\d]

非数字

\W

[^\w]

非字符,和文化字体有关

\S

[^\s]

非空格,回车和tab。和文化字体有关

在”[]”使用否定预订一字符集时要特别心。[\D\S]不等于[^\d\s]。[^\d\s]会匹配除了数字和空白符以外的所有字符。而[\D\S]会匹配要么不是一个数字,要么是空白符。因为数字不是空白符,空白符也不是数字,所以[\D\S]会匹配任意的字符。

3.1.6限定符

有时候不知道要匹配多少字符。为了能适应这种不确定性,正则表达式支持限定符的概念。这些限定符可以指定正则表达式的一个给定组件必须要出现多少次才能满足匹配。

下表给出了各种限定符及其含义的说明:

* 匹配前面的子表达式零次或多次。例如,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?'。请注意在逗号和两个数之间不能有空格。

对一个很大的输入文档而言,章节数很轻易就超过九章,因此需要有一种方法来处理两位数或者三位数的章节号。限定符就提供了这个功能。下面的JScript 正则表达式可以匹配具有任何位数的章节标题:

/Chapter [1-9][0-9]*/

下面的 VBScript 正则表达式执行同样的匹配:

"Chapter [1-9][0-9]*"

请注意限定符出现在范围表达式之后。因此,它将应用于所包含的整个范围表达式,在本例中,只指定了从 0 到 9 的数字。

这里没有使用 '+' 限定符,因为第二位或后续位置上并不一定需要一个数字。同样也没有使用 '?' 字符,因为这将把章节数限制为只有两位数字。在 'Chapter' 和空格字符之后至少要匹配一个数字。

如果已知章节数限制只有99 章,则可以使用下面的 JScript 表达式来指定至少有一位数字,但不超过两个数字。

/Chapter [0-9]{1,2}/

对 VBScript 可以使用下述正则表达式:

"Chapter [0-9]{1,2}"

上述表达式的缺点是如果有一个章节号大于 99,它仍只会匹配前两位数字。另一个缺点是某些人可以创建一个 Chapter 0,而且仍能匹配。一个更好的用来匹配两位数的 JScript 表达式如下:/Chapter [1-9][0-9]?/

或者

/Chapter [1-9][0-9]{0,1}/

对 VBScript 而言,下述表达式与上面等价:

"Chapter [1-9][0-9]?"

或者

"Chapter [1-9][0-9]{0,1}"

'*'、 '+'和 '?' 限定符都称之为贪婪的,也就是说,他们尽可能多地匹配文字。有时这根本就不是所希望发生的情况。有时则正好希望最小匹配。

例如,你可能要搜索一个 HTML 文档来查找一处包含在 H1 标记中的章节标题。在文档中该文字可能具有如下形式:

Chapter 1 – Introduction to Regular Expressions

下面的表达式匹配从开始的小于号 (<) 到 H1 标记结束处的大于号之间的所有内容。

/<.*>/

VBScript 的正则表达式为:

"<.*>"

如果所要匹配的就是开始的 H1 标记,则下述非贪婪地表达式就只匹配

/<.*?>/

或者

"<.*?>"

通过在 '*'、 '+' 或 '?' 限定符后放置 '?',该表达式就从贪婪匹配转为了非贪婪或最小匹配。

我们都明白

()可以为以规则匹配后获取匹配集合,用RegExp.$1-$9来获取;

但规则匹配以非贪婪限制匹配后,将无匹配集合返回;

我们来讨论下非贪婪匹配与贪婪匹配

首先

(?:pattern)

匹配 pattern 但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。这在使用"或" 字符 (|) 来组合一个模式的各个部分是很有用。例如, 'industr(?:y|ies) 就是一个比 'industry|industries' 更简略的表达式。

(?=pattern)

正向预查,在任何匹配 pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如, 'Windows (?=95|98|NT|2000)' 能匹配 "Windows 2000" 中的 "Windows" ,但不能匹配 "Windows 3.1" 中的 "Windows"。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。

(?!pattern)

负向预查,在任何不匹配Negative lookahead matches the search string at any point where a string not matching pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如'Windows (?!95|98|NT|2000)' 能匹配 "Windows 3.1" 中的"Windows",但不能匹配 "Windows 2000" 中的 "Windows"。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始

3.1.7什么是贪婪匹配?

“贪婪匹配”原则是说,当解释器将代码中的字符解析成一个个的编译器在处理代码时眼中看到的最小语法单元时,编译器会使用一种贪婪匹配算法,也就是说会尽可能让一个单元包含更多的字符。

3.1.8非贪婪匹配的效率

可能有不少的人和我一样,有过这样的经历:当我们要匹配类似 "内容" 或者"加粗" 这样的文本时,我们根据正向预搜索功能写出这样的表达式:"([^<]|<(?!/td>))*" 或者 "((?!).)*"。

当发现非贪婪匹配之时,恍然大悟,同样功能的表达式可以写得如此简单:".*?"。顿时间如获至宝,凡是按边界匹配的地方,尽量使用简捷的非贪婪匹配 ".*?"。特别是对于复杂的表达式来说,采用非贪婪匹配 ".*?" 写出来的表达式的确是简练了许多。

然而,当一个表达式中,有多个非贪婪匹配时,或者多个未知匹配次数的表达式时,这个表达式将可能存在效率上的陷阱。有时候,匹配速度慢得莫名奇妙,甚至开始怀疑正则表达式是否实用。

3.1.9效率陷阱的产生:

非贪婪匹配:”如果少匹配就会导致整个表达式匹配失败的时候,与贪婪模式类似,非贪婪模式会最小限度的再匹配一些,以使整个表达式匹配成功。”

具体的匹配过程是这样的:

"非贪婪部分" 先匹配最少次数,然后尝试匹配"右侧的表达式"。

如果右侧的表达式匹配成功,则整个表达式匹配结束。如果右侧表达式匹配失败,则"非贪婪部分" 将增加匹配一次,然后再尝试匹配"右侧的表达式"。

如果右侧的表达式又匹配失败,则"非贪婪部分" 将再增加匹配一次。再尝试匹配"右侧的表达式"。

依此类推,最后得到的结果是"非贪婪部分" 以尽可能少的匹配次数,使整个表达式匹配成功。或者最终仍然匹配失败。

当一个表达式中有多个非贪婪匹配,以表达式 "d(\w+?)d(\w+?)z" 为例,对于第一个括号中的"\w+?" 来说,右边的 "d(\w+?)z" 属于它的"右侧的表达式",对于第二个括号中的 "\w+?" 来说,右边的 "z" 属于它的"右侧的表达式"。

当 "z" 匹配失败时,第二个 "\w+?" 会"增加匹配一次",再尝试匹配 "z"。如果第二个 "\w+?" 无论怎样"增加匹配次数",直至整篇文本结束,"z" 都不能匹配,那么表示 "d(\w+?)z" 匹配失败,也就是说第一个 "\w+?" 的"右侧" 匹配失败。此时,第一个 "\w+?" 会增加匹配一次,然后再进行 "d(\w+?)z" 的匹配。循环前面所讲的过程,直至第一个 "\w+?" 无论怎么"增加匹配次数",后边的 "d(\w+?)z" 都不能匹配时,整个表达式才宣告匹配失败。

其实,为了使整个表达式匹配成功,贪婪匹配也会适当的”让出”已经匹配的字符。因此贪婪匹配也有类似的情况。当一个表达式中有较多的未知匹配次数的表达式时,为了让整个表达式匹配成功,各个贪婪或非贪婪的表达式都要进行尝试减少或增加匹配次数,由此容易形成一个大循环的尝试,造成了很长的匹配时间。本文之所以称之为”陷阱”,因为这种效率问题往往不易察觉。

举例:"d(\w+?)d(\w+?)d(\w+?)z" 匹配 "ddddddddddd..." 时,将花费较长一段时间才能判断出匹配失败。

3.1.10效率陷阱的避免:

避免效率陷阱的原则是:避免”多重循环”的”尝试匹配”。并不是说非贪婪匹配就是不好的,只是在运用非贪婪匹配的时候,需要注意避免过多”循环尝试”的问题。

情况一:对于只有一个非贪婪或者贪婪匹配的表达式来说,不存在效率陷阱。也就是说,要匹配类似 " 内容 " 这样的文本,表达式 "([^<]|<(?!/td>))*" 和"((?!).)*" 和 ".*?" 的效率是完全相同的。

情况二:如果一个表达式中有多个未知匹配次数的表达式,应防止进行不必要的尝试匹配。

比如,对表达式 "" 来说,如果前面部分表达式在遇到"" 却匹配失败,将导致第一个 ".*?" 增加匹配次数再尝试。而对于表达式真正目的,让第一个 ".*?" 增加匹配成”vbscript'>“是不对的,因此这种尝试是不必要的尝试。

因此,对依靠边界来识别的表达式,不要让未知匹配次数的部分跨过它的边界。前面的表达式中,第一个 ".*?" 应该改写成 "[^']*"。后边那个 ".*?" 的右边再没有未知匹配次数的表达式,因此这个非贪婪匹配没有效率陷阱。于是,这个匹配脚本块的表达式,应该写成:"" 更好。

1.贪婪:+,*,?,{m,n}等默认是贪婪匹配,即尽可能多匹配,也叫最大匹配

如果后面加上?,就转化为非贪婪匹配,需要高版本支持

2.获取:默认用(x|y)是获取匹配,很多时候只是测试,不一定要求得到所匹配的数据,尤其在嵌套匹配或大数据中就要用非获取匹配(?:x|y),这样提高了效率,优化了程序。

3.消耗:默认是消耗匹配,一般在预查中是非消耗匹配。

举个例子,2003-2-8要变为2003-02-08

如果用/-(\d)-/第二次匹配将从8开始,从而只替换第一个2,错误

如果用/-(\d)(?=-)/则第二次匹配从第二个-开始,即不消耗字符-

4.预查:js中分为正向预查和负向预查

如上面的(?=pattern)是正向预查,在任何匹配 pattern 的字符串开始处匹配查找字符串。还有

(?!pattern)是负向预查,在任何不匹配 pattern 的字符串开始处匹配查找字符串。负向预查有时会用在对[^]的扩充,[^]只是一些字符,而?!可以使整个字符串。

5.回调:一般用在替换上,即根据不用的匹配内容返回不用的替换值,从而简化了程序,需要高版本支持

6.引用:\num 对所获取的第num个匹配的引用。

例如,'(.)\1\1' 匹配AAA型。'(.)(.)\2\1' 匹配ABBA型。

上面好象有提过正则表达式的界定符.(忘记了没关系我们再来)

界定符:一个表达式被包含的区域. 在javascript中我们比较常用的是/作为整体匹配模式的界定符

在PHP中任何不是字母、数字或反斜线(\)的字符都可以作为定界符。如果作为定界符的字符必须被用在表达式本身中,则需要用反斜线转义。

界定符可以分为

一:整体匹配模式符号

二:字符类(簇)定界符例如:[]

三:子模式符 ();

四:数量匹配符 {};

一个模式的建立

javascript中可以以两种形式

一:界定式例如var Reg = /^javascript$/ig;

二:实例化RegExp对象var Reg = new RegExp("^javascript$","ig");PS:本人一直不喜欢这种形式,只要原因为跟perl规范差很多.有点像PHP的ereg.. 最近也因为这个问题.费了点时间在关于PHP引号中转义符号的匹配问题.个人建议初学或者为了以后进步才用第一种形式.

在一个匹配模式建立后.如何使用子模式呢.其实在前面一些正则语法中已经提过了.今天我们再来间单的说下.

用个典型的例子说明吧

/<(.*)>.*<\/\1>/ PS:其实这个表达式是有缺陷的,不过我们先不说.

看了前面几次的说明,我想应该知道<(.*)>的作用了,那后面的<\/\1>中的第一个\也就是我们文章开头说的转义定界符,而\1就是取子模这里跟javascript的RegExp对象的$0-$9不同是从1开始的.

也正是如此这个表达式才能匹配简单的无属性html标签例如body;

JS正则表达式大全

JS正则表达式大全 JS正则表达式大全【1】 正则表达式中的特殊字符【留着以后查用】字符含意 \ 做为转意,即通常在"\"后面的字符不按原来意义解释,如/b/匹配字符"b",当b前面加了反斜杆后/\b/,转意为匹配一个单词的边界。 -或- 对正则表达式功能字符的还原,如"*"匹配它前面元字符0次或多次,/a*/将匹配a,aa,aaa,加了"\"后,/a\*/将只匹配"a*"。 ^ 匹配一个输入或一行的开头,/^a/匹配"an A",而不匹配"An a" $ 匹配一个输入或一行的结尾,/a$/匹配"An a",而不匹配"an A" * 匹配前面元字符0次或多次,/ba*/将匹配b,ba,baa,baaa + 匹配前面元字符1次或多次,/ba*/将匹配ba,baa,baaa ? 匹配前面元字符0次或1次,/ba*/将匹配b,ba (x) 匹配x保存x在名为$1...$9的变量中 x|y 匹配x或y {n} 精确匹配n次 {n,} 匹配n次以上 {n,m} 匹配n-m次 [xyz] 字符集(character set),匹配这个集合中的任一一个字符(或元字符) [^xyz] 不匹配这个集合中的任何一个字符 [\b] 匹配一个退格符 \b 匹配一个单词的边界 \B 匹配一个单词的非边界 \cX 这儿,X是一个控制符,/\cM/匹配Ctrl-M \d 匹配一个字数字符,/\d/ = /[0-9]/ \D 匹配一个非字数字符,/\D/ = /[^0-9]/ \n 匹配一个换行符 \r 匹配一个回车符 \s 匹配一个空白字符,包括\n,\r,\f,\t,\v等 \S 匹配一个非空白字符,等于/[^\n\f\r\t\v]/ \t 匹配一个制表符 \v 匹配一个重直制表符 \w 匹配一个可以组成单词的字符(alphanumeric,这是我的意译,含数字),包括下划线,如[\w]匹配

Find用法详解(含正则表达式)

Sed基础用法篇 刚开始接触linux,其实还是老实用vim来编辑文件,不过同样的过程重复多次,你就要想办法简化你的过程。sed绝对是一个好的命令或者工具,你不需要用vim打开文件就可以直接编辑(推荐掌握以下用法)。 1、删除行首空格 sed 's/^[ ]*//g' filename sed 's/^ *//g' filename sed 's/^[[:space:]]*//g' filename 2、行后和行前添加新行 行后:sed 's/pattern/&\n/g' filename 行前:sed 's/pattern/\n&/g' filename &代表pattern 3、使用变量替换(使用双引号) sed ‐e "s/$var1/$var2/g" filename 4、在第一行前插入文本 sed ‐i '1 i\插入字符串' filename 5、在最后一行插入 sed ‐i '$ a\插入字符串' filename

6、在匹配行前插入 sed ‐i '/pattern/ i "插入字符串"' filename 7、在匹配行后插入 sed ‐i '/pattern/ a "插入字符串"' filename 8、删除文本中空行和空格组成的行以及#号注释的行 grep ‐v ^# filename | sed /^[[:space:]]*$/d | sed /^$/d 9、要将目录/modules下面所有文件中的zhangsan都修改成list,可用如下命令:(注意备份原文件) sed ‐i 's/zhangsan/list/g' `grep zhangsan ‐rl /modules` Linux命令FIND详解 由于find具有强大的功能,所以它的选项也很多,其中大部分选项都值得我们花时间来了解一下。即使系统中含有网络文件系统( NFS),find命令在该文件系统中同样有效,只你具有相应的权限。在运行一个非常消耗资源的find命令时,很多人都倾向于把它放在后台执行,因为遍历一个大的文件系统可能会花费很长的时间(这里是指30G字节以上的文件系统)。 一、find 命令格式 1、find命令的一般形式为; find pathname ‐options [‐print ‐exec ‐ok ...]

正则表达式.DOC

正则表达式 第一部分: ----------------- 正则表达式(REs)通常被错误地认为是只有少数人理解的一种神秘语言。在表面上它们确实看起来杂乱无章,如果你不知道它的语法,那么它的代码在你眼里只是一堆文字垃圾而已。实际上,正则表达式是非常简单并且可以被理解。读完这篇文章后,你将会通晓正则表达式的通用语法。 支持多种平台 正则表达式最早是由数学家Stephen Kleene于1956年提出,他是在对自然语言的递增研究成果的基础上提出来的。具有完整语法的正则表达式使用在字符的格式匹配方面上,后来被应用到熔融信息技术领域。自从那时起,正则表达式经过几个时期的发展,现在的标准已经被ISO(国际标准组织)批准和被Open Group 组织认定。 正则表达式并非一门专用语言,但它可用于在一个文件或字符里查找和替代文本的一种标准。它具有两种标准:基本的正则表达式(BRE),扩展的正则表达式(ERE)。ERE包括BRE功能和另外其它的概念。 许多程序中都使用了正则表达式,包括xsh,egrep,sed,vi以及在UNIX平台下的程序。它们可以被很多语言采纳,如HTML和XML,这些采纳通常只是整个标准的一个子集。 比你想象的还要普通 随着正则表达式移植到交叉平台的程序语言的发展,这的功能也日益完整,使用也逐渐广泛。网络上的搜索引擎使用它,e-mail程序也使用它,即使你不是一个UNIX程序员,你也可以使用规则语言来简化你的程序而缩短你的开发时间。 正则表达式101 很多正则表达式的语法看起来很相似,这是因为你以前你没有研究过它们。通配符是RE的一个结构类型,即重复操作。让我们先看一看ERE标准的最通用的基本语法类型。为了能够提供具有特定用途的范例,我将使用几个不同的程序。

正则表达式

正则表达式 一、什么是这则表达式 正则表达式(regular expressions)是一种描述字符串集的方法,它是以字符串集中各字符串的共有特征为依据的。正则表达式可以用于搜索、编辑或者是操作文本和数据。它超出了java程序设计语言的标准语法,因此有必要去学习特定的语法来构建正则表达式。一般使用的java.util.regex API所支持的正则表达式语法。 二、测试用具 import java.io.BufferedReader; import java.io.InputStreamReader; import java.util.Scanner; import java.util.regex.Matcher; import java.util.regex.Pattern; public class Regex{ public static void main(String[]args)throws Exception{ BufferedReader br=new BufferedReader(new InputStreamReader(System.in)); if(br==null){ System.out.println("没有输入任何数据"); System.exit(1); } while(true){ System.out.print("输入表达式:"); Pattern pattern=https://www.360docs.net/doc/e616874269.html,pile(br.readLine()); System.out.print("输入字符串:"); Matcher matcher=pattern.matcher(br.readLine()); boolean found=false; while(matcher.find()){ System.out.println("找到子字符串"+matcher.group()+" 开始于索引"+matcher.start()+"结束于索引"+matcher.end()+"\n") found=true; } if(!found){ System.out.println("没有找到子字符串\n"); } } } }

正则表达式语法完整版

正则表达式基础知识 一个正则表达式就是由普通字符(例如字符a 到z)以及特殊字符(称为元字符)组成的文字模式。该模式描述在查找文字主体时待匹配的一个或多个字符串。正则表达式作为一个模板,将某个字符模式与所搜索的字符串进行匹配。如:

下面看几个例子: "^The":表示所有以"The"开始的字符串("There","The cat"等); "of despair$":表示所以以"of despair"结尾的字符串; "^abc$":表示开始和结尾都是"abc"的字符串——呵呵,只有"abc"自己了;"notice":表示任何包含"notice"的字符串。 '*','+'和'?'这三个符号,表示一个或一序列字符重复出现的次数。它们分别表示“没有或更多”,“一次或更多”还有“没有或一次”。下面是几个例子: "ab*":表示一个字符串有一个a后面跟着零个或若干个b。("a", "ab", "abbb",……);"ab+":表示一个字符串有一个a后面跟着至少一个b或者更多; "ab?":表示一个字符串有一个a后面跟着零个或者一个b; "a?b+$":表示在字符串的末尾有零个或一个a跟着一个或几个b。 也可以使用范围,用大括号括起,用以表示重复次数的范围。 "ab{2}":表示一个字符串有一个a跟着2个b("abb"); "ab{2,}":表示一个字符串有一个a跟着至少2个b; "ab{3,5}":表示一个字符串有一个a跟着3到5个b。

请注意,你必须指定范围的下限(如:"{0,2}"而不是"{,2}")。 还有,你可能注意到了,'*','+'和'?'相当于"{0,}","{1,}"和"{0,1}"。 还有一个'|',表示“或”操作: "hi|hello":表示一个字符串里有"hi"或者"hello"; "(b|cd)ef":表示"bef"或"cdef"; "(a|b)*c":表示一串"a""b"混合的字符串后面跟一个"c"; '.'可以替代任何字符: "a.[0-9]":表示一个字符串有一个"a"后面跟着一个任意字符和一个数字; "^.{3}$":表示有任意三个字符的字符串(长度为3个字符); 方括号表示某些字符允许在一个字符串中的某一特定位置出现: "[ab]":表示一个字符串有一个"a"或"b"(相当于"a|b"); "[a-d]":表示一个字符串包含小写的'a'到'd'中的一个(相当于"a|b|c|d"或者"[abcd]");"^[a-zA-Z]":表示一个以字母开头的字符串; "[0-9]%":表示一个百分号前有一位的数字; "[0-9]+":表示一个以上的数字; ",[a-zA-Z0-9]$":表示一个字符串以一个逗号后面跟着一个字母或数字结束。 你也可以在方括号里用'^'表示不希望出现的字符,'^'应在方括号里的第一位。(如:"%[^a-zA-Z]%"表 示两个百分号中不应该出现字母)。 为了逐字表达,必须在"^.$()|*+?{\"这些字符前加上转移字符'\'。 请注意在方括号中,不需要转义字符。

正则表达式经典手册

引言 正则表达式(regular expression)就是用一个“表达式”来描述一个特征,然后去验证另一个“字符串”是否符合这个特征。比如表达式“ab+” 描述的特征是“一个 'a' 和任意个'b' ”,那么 'ab', 'abb', 'abbbbbbbbbb' 都符合这个特征。 正则表达式可以用来:(1)验证字符串是否符合指定特征,比如验证是否是合法的邮件地址。(2)用来查找字符串,从一个长的文本中查找符合指定特征的字符串,比查找固定字符串更加灵活方便。(3)用来替换,比普通的替换更强大。 正则表达式学习起来其实是很简单的,不多的几个较为抽象的概念也很容易理解。之所以很多人感觉正则表达式比较复杂,一方面是因为大多数的文档没有做到由浅入深地讲解,概念上没有注意先后顺序,给读者的理解带来困难;另一方面,各种引擎自带的文档一般都要介绍它特有的功能,然而这部分特有的功能并不是我们首先要理解的。 文章中的每一个举例,都可以点击进入到测试页面进行测试。闲话少说,开始。 1. 正则表达式规则 1.1 普通字符 字母、数字、汉字、下划线、以及后边章节中没有特殊定义的标点符号,都是"普通字符"。表达式中的普通字符,在匹配一个字符串的时候,匹配与之相同的一个字符。 举例1:表达式 "c",在匹配字符串 "abcde" 时,匹配结果是:成功;匹配到的内容是:"c";匹配到的位置是:开始于2,结束于3。(注:下标从0开始还是从1开始,因当前编程语言的不同而可能不同) 举例2:表达式 "bcd",在匹配字符串 "abcde" 时,匹配结果是:成功;匹配到的内容是:"bcd";匹配到的位置是:开始于1,结束于4。 1.2 简单的转义字符 一些不便书写的字符,采用在前面加 "\" 的方法。这些字符其实我们都已经熟知了。

QT正则表达式QRegExp的解析

QRegExp正则表达式 2010-03-20 17:00 "^\d+$" //非负整数(正整数 + 0) "^[0-9]*[1-9][0-9]*$" //正整数 "^((-\d+)|(0+))$" //非正整数(负整数 + 0) "^-[0-9]*[1-9][0-9]*$" //负整数 "^-?\d+$" //整数 "^\d+(\.\d+)?$" //非负浮点数(正浮点数 + 0) "^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$" //正浮点数 "^((-\d+(\.\d+)?)|(0+(\.0+)?))$" //非正浮点数(负浮点数 + 0) "^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[ 1-9][0-9]*)))$" //负浮点数 "^(-?\d+)(\.\d+)?$" //浮点数 "^[A-Za-z]+$" //由26个英文字母组成的字符串 "^[A-Z]+$" //由26个英文字母的大写组成的字符串 "^[a-z]+$" //由26个英文字母的小写组成的字符串 "^[A-Za-z0-9]+$" //由数字和26个英文字母组成的字符串 "^\w+$" //由数字、26个英文字母或者下划线组成的字符串 "^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$" //email地址 "^[a-zA-z]+://(\w+(-\w+)*)(\.(\w+(-\w+)*))*(\?\S*)?$" //url "^(d{2}|d{4})-((0([1-9]{1}))|(1[1|2]))-(([0-2]([1-9]{1}))|(3[0|1]))$" // 年-月-日 "^((0([1-9]{1}))|(1[1|2]))/(([0-2]([1-9]{1}))|(3[0|1]))/(d{2}|d{4})$" // 月/日/年 "^([w-.]+)@(([[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.)|(([w-]+.)+))([a-zA-Z ]{2,4}|[0-9]{1,3})(]?)$" //Email "(d+-)?(d{4}-?d{7}|d{3}-?d{8}|^d{7,8})(-d+)?" //电话号码 "^(d{1,2}|1dd|2[0-4]d|25[0-5]).(d{1,2}|1dd|2[0-4]d|25[0-5]).(d{1,2}|1 dd|2[0-4]d|25[0-5]).(d{1,2}|1dd|2[0-4]d|25[0-5])$" //IP地址 ^([0-9A-F]{2})(-[0-9A-F]{2}){5}$ //MAC地址的正则表达式 ^[-+]?\d+(\.\d+)?$ //值类型正则表达式 QRegExp是Qt的正则表达式类. Qt中有两个不同类的正则表达式. 第一类为元字符.它表示一个或多个常量表达式. 令一类为转义字符,它代表一个特殊字符. 一.元字符 . 匹配任意单个字符.例如, 1.3 可能是1. 后面跟任意字符,再跟3 ^ 匹配字符串首. 例如, ^12可能是123,但不能是312

正则表达式

多少年来,许多的编程语言和工具都包含对正则表达式的支持,.NET基础类库中包含有一个名字空间和一系列可以充分发挥规则表达式威力的类,而且它们也都与未来的Perl 5中的规则表达式兼容。 此外,regexp类还能够完成一些其他的功能,例如从右至左的结合模式和表达式的编辑等。 在这篇文章中,我将简要地介绍System.Text.RegularExpression中的类和方法、一些字符串匹配和替换的例子以及组结构的详细情况,最后,还会介绍一些你可能会用到的常见的表达式。 应该掌握的基础知识 规则表达式的知识可能是不少编程人员“常学常忘”的知识之一。在这篇文章中,我们将假定你已经掌握了规则表达式的用法,尤其是Perl 5中表达式的用法。.NET的regexp类是Perl 5中表达式的一个超集,因此,从理论上说它将作为一个很好的起点。我们还假设你具有了C#的语法和.NET架构的基本知识。 如果你没有规则表达式方面的知识,我建议你从Perl 5的语法着手开始学习。在规则表达式方面的权威书籍是由杰弗里?弗雷德尔编写的《掌握表达式》一书,对于希望深刻理解表达式的读者,我们强烈建议阅读这本书。 RegularExpression组合体 regexp规则类包含在System.Text.RegularExpressions.dll文件中,在对应用软件进行编译时你必须引用这个文件,例如: csc r:System.Text.RegularExpressions.dll foo.cs 命令将创建foo.exe文件,它就引用了System.Text.RegularExpressions文件。 名字空间简介 在名字空间中仅仅包含着6个类和一个定义,它们是: Capture: 包含一次匹配的结果; CaptureCollection: Capture的序列; Group: 一次组记录的结果,由Capture继承而来; Match: 一次表达式的匹配结果,由Group继承而来; MatchCollection: Match的一个序列; MatchEvaluator: 执行替换操作时使用的代理; Regex: 编译后的表达式的实例。 Regex类中还包含一些静态的方法: Escape: 对字符串中的regex中的转义符进行转义; IsMatch: 如果表达式在字符串中匹配,该方法返回一个布尔值; Match: 返回Match的实例; Matches: 返回一系列的Match的方法; Replace: 用替换字符串替换匹配的表达式; Split: 返回一系列由表达式决定的字符串; Unescape:不对字符串中的转义字符转义。

《易语言“正则表达式”详细教程》

《易语言“正则表达式”教程》 本文改编自多个文档,因此如有雷同,不是巧合。 “正则表达式”的应用范围越来越广,有了这个强大的工具,我们可以做很多事情,如搜索一句话中某个特定的数据,屏蔽掉一些非法贴子的发言,网页中匹配特定数据,代码编辑框中字符的高亮等等,这都可以用正则表达式来完成。 本书分为四个部分。 第一部分介绍了易语言的正则表达式支持库,在这里,大家可以了解第一个正则表达式的易语言程序写法,以及一个通用的小工具的制作。 第二部分介绍了正则表达式的基本语法,大家可以用上述的小工具进行试验。 第三部分介绍了用易语言写的正则表达式工具的使用方法。这些工具是由易语言用户提供的,有的工具还带有易语言源码。他们是:monkeycz、零点飞越、寻梦。 第四部分介绍了正则表达式的高级技巧。 目录 《易语言“正则表达式”教程》 (1) 目录 (1) 第一章易语言正则表达式入门 (3) 一.与DOS下的通配符类似 (3) 二.初步了解正则表达式的规定 (3) 三.一个速查列表 (4) 四.正则表达式支持库的命令 (5) 4.1第1个正则表达式程序 (5) 4.2第2个正则表达式例程 (7) 4.3第3个例程 (8) 4.4一个小型的正则工具 (9) 第二章揭开正则表达式的神秘面纱 (11) 引言 (12) 一.正则表达式规则 (12) 1.1普通字符 (12) 1.2简单的转义字符 (13) 1.3能够与“多种字符”匹配的表达式 (14) 1.4自定义能够匹配“多种字符”的表达式 (16) 1.5修饰匹配次数的特殊符号 (17) 1.6其他一些代表抽象意义的特殊符号 (20) 二.正则表达式中的一些高级规则 (21) 2.1匹配次数中的贪婪与非贪婪 (21)

很完整的一篇正则表达式总结

1、正则表达式-完结篇---工具类开发--- ? 1 2 3 4 5 6 7 8 9 1 0 1 1 1 2 1 3 1 4 1 '/.+/', 'email'=> '/^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/', 'url'=> '/^http(s?):\/\/(?:[A-za-z0-9-]+\.)+[A-za-z]{2,4}(?:[\/ \?#][\/=\?%\-&~`@[\]\':+!\.#\w]*)?$/', 'currency'=> '/^\d+(\.\d+)?$/', 'number'=> '/^\d+$/', 'zip'=> '/^\d{6}$/', 'integer'=> '/^[-\+]?\d+$/', 'double'=> '/^[-\+]?\d+(\.\d+)?$/',

5 1 6 1 7 1 8 1 9 2 0 2 1 2 2 2 3 2 4 2 5 2 6 2'english'=> '/^[A-Za-z]+$/', 'qq'=> '/^\d{5,11}$/', 'mobile'=> '/^1(3|4|5|7|8)\d{9}$/', ); //定义其他属性 private$returnMatchResult=false; //返回类型判断 private$fixMode=null; //修正模式 private$matches=array(); //存放匹配结果 private$isMatch=false; //构造函数,实例化后传入默认的两个参数 public function __construct($returnMatchResult=false,$fixMode=null){ $this->returnMatchResult=$returnMatchResult; $this->fixMode=$fixMode; } //判断返回结果类型,为匹配结果matches还是匹配成功与否isMatch,并调用返回方法 private function regex($pattern,$subject){ if(array_key_exists(strtolower($pattern), $this->validate)) $pattern=$this->validate[$pattern].$this->fixMode; //判断后再连接上修正模式作为匹配的正则表达式 $this->returnMatchResult ?

PYTHON正则表达式模块RE讲解

2re模块的基本函数 在上面的说明中,我们已经对re模块的基本函数‘findall’很熟悉了。当然如果光有findall 的话,很多功能是不能实现的。下面开始介绍一下re模块其它的常用基本函数。灵活搭配使用这些函数,才能充分发挥Python正则式的强大功能。 首先还是说下老熟人findall函数吧 findall(rule,target[,flag]) 在目标字符串中查找符合规则的字符串。 第一个参数是规则,第二个参数是目标字符串,后面还可以跟一个规则选项(选项功能将在compile函数的说明中详细说明)。 返回结果结果是一个列表,中间存放的是符合规则的字符串。如果没有符合规则的字符串被找到,就返回一个空列表。 2.1使用compile加速 compile(rule[,flag]) 将正则规则编译成一个Pattern对象,以供接下来使用。 第一个参数是规则式,第二个参数是规则选项。 返回一个Pattern对象 直接使用findall(rule,target)的方式来匹配字符串,一次两次没什么,如果是多次使用的话,由于正则引擎每次都要把规则解释一遍,而规则的解释又是相当费时间的,所以这样的效率就很低了。如果要多次使用同一规则来进行匹配的话,可以使用https://www.360docs.net/doc/e616874269.html,pile函数来将规则预编译,使用编译过返回的Regular Expression Object或叫做Pattern对象来进行查找。 >>>s='111,222,aaa,bbb,ccc333,444ddd' >>>rule=r’\b\d+\b’ >>>compiled_rule=https://www.360docs.net/doc/e616874269.html,pile(rule) >>>compiled_rule.findall(s) ['111','222'] 可见使用compile过的规则使用和未编译的使用很相似。compile函数还可以指定一些规则标志,来指定一些特殊选项。多个选项之间用’|’(位或)连接起来。 I IGNORECASE忽略大小写区别。 L LOCAL字符集本地化。这个功能是为了支持多语言版本的字符集使用环境的,比如在转义符\w,在英文环境下,它代表[a-zA-Z0-9],即所以英文字符和数字。如果在一个法语环境下使用,缺省设置下,不能匹配"é"或"?"。加上这L选项和就可以匹配了。不过这个对于中文环境似乎没有什么用,它仍然不能匹配中文字符。 M MULTILINE多行匹配。在这个模式下’^’(代表字符串开头)和’$’(代表字符串结尾)将能够匹配多行的情况,成为行首和行尾标记。比如 >>>s=’123456\n789012\n345678’ >>>rc=https://www.360docs.net/doc/e616874269.html,pile(r’^\d+’)#匹配一个位于开头的数字,没有使用M选项 >>>rc.findall(s) ['123']#结果只能找到位于第一个行首的’123’ >>>rcm=https://www.360docs.net/doc/e616874269.html,pile(r’^\d+’,re.M)#使用M选项 >>>rcm.findall(s) ['123','789','345']#找到了三个行首的数字

正则表达式

正则表达式
目录
1. 引言 2. 基本语法 3. sed 4. awk 5. 练习:在 C 语言中使用正则表达式
1. 引言
以前我们用 grep 在一个文件中找出包含某些字符串的行,比如在头文件中找出一个宏定义. 其实 grep 还可以找出符合某个模式(Pattern)的一类字符串.例如找出所有符合 xxxxx@xxxx.xxx 模式的字符串(也就是 email 地址),要求 x 字符可以是字母,数字,下划 线,小数点或减号,email 地址的每一部分可以有一个或多个 x 字符,例如 abc.d@https://www.360docs.net/doc/e616874269.html,, 1_2@987-6.54,当然符合这个模式的不全是合法的 email 地址,但至少可以做一次初步筛选, 筛掉 a.b,c@d 等肯定不是 email 地址的字符串.再比如,找出所有符合 yyy.yyy.yyy.yyy 模 式的字符串(也就是 IP 地址),要求 y 是 0-9 的数字,IP 地址的每一部分可以有 1-3 个 y 字 符. 如果要用 grep 查找一个模式,如何表示这个模式,这一类字符串,而不是一个特定的字符串 呢?从这两个简单的例子可以看出,要表示一个模式至少应该包含以下信息: 字符类(Character Class):如上例的 x 和 y,它们在模式中表示一个字符,但是取 值范围是一类字符中的任意一个. 数量限定符(Quantifier): 邮件地址的每一部分可以有一个或多个 x 字符,IP 地址 的每一部分可以有 1-3 个 y 字符 各种字符类以及普通字符之间的位置关系:例如邮件地址分三部分,用普通字符@和. 隔开,IP 地址分四部分,用.隔开,每一部分都可以用字符类和数量限定符描述.为 了表示位置关系,还有位置限定符(Anchor)的概念,将在下面介绍.
规定一些特殊语法表示字符类,数量限定符和位置关系,然后用这些特殊语法和普通字符一 起表示一个模式,这就是正则表达式(Regular Expression).例如 email 地址的正则表达式 可以写成[a-zA-Z0-9_.-]+@[a-zA-Z0-9_.-]+\.[a-zA-Z0-9_.-]+,IP 地址的正则表达式可以 写成[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}.下一节介绍正则表达式的语法, 我们先看看正则表达式在 grep 中怎么用.例如有这样一个文本文件 testfile:
192.168.1.1
第 1 页 共 10 页

词法分析小结

词法分析小结 -总结 []词法是编译器的第一阶段,它的工作就是从输入(源代码)中取得token,以作为parser (语法分析)的输入,一般在词法分析阶段都会把一些无用的空白字符(white space,即空格、tab和换行)以及注释剔除,以降低下一步分析的复杂度,词法分析器一般会提供一个gettoken()这样的,parser可以在做语法分析时调用词法分析器的这个方法来得到下一个token,所以词法分析器并不是一次性遍历所有源代码,而是采取这种on-demand的方式:只在parser需要时才工作,并且每次只取一个token,。token和lexeme 首先,token不等于lexeme。token和lexeme的关系就类似于面向对象语言中“类”和“实例”(或“对象”)之间的关系,这个用中文不知该如何解释才好,比如语言中的变量a和b,它们都属于同一种token:identifier,而a的lexeme是”a”,b则是”b”,而每个关键字都是一种token。token 可以附带有一个值属性,例如变量a,当调用词法分析器的gettoken()时,会返回一个identifier类型的token,这个token带有一个属性“a”,属性可以是多样的,例如表示数字的token可以带有一个表示数字值的属性,它是整型的。如下代码:int age = 23;int count = 50;可以依次提取出8个token:int(值为”int”),id(值为”age”),assign(值为”=”),number(值为整型数值23),int(值为”int”),id(值为”count”),assign(值为”=”),number(值为50)正则表达式 正则表达式可以用来描述字符串模式,例如我们可以用digit+来表示number的token,其中digit表示单个数字(这里说正则表达式并不完全和实现的正则引擎所识别的正则表达式等价,这里只是为了描述问题而已)。然而像c语言的的多行注释,用正则表达式来描述就比较麻烦,此时更倾向于直接用有穷自动机(finite automaton)来描述,因为用它来描述非常直观且很容易。有穷自动机(finite automata) 有穷自动机也称为有限状态机,状态在输入字符的作用下发生迁移,因此,它可以用来识别token,也因此,我们只要画得出fa,之后再用代码实现这个fa,那词法分析器也就差不多弄好了。有穷自动机分确定性(dfa)和非确定性(nfa)两种,如果对于同一个输入,只会有一个确定的状态迁移线,也就是只有一个确定的“下一状态”,那就是dfa,否则就是nfa。因为dfa对于同一个输入只有一个确定的下一状态,所以词法分析器当然优先采用它,那nfa拿来干嘛用呢?nfa用来做描述用时更方便,我们可以非常迅速地画出一个识别token的nfa图,但要想直接画出个dfa那要动不少脑筋。根据正则表达式构建nfa 如上所述,nfa更容易画出,那我们就先研究nfa,在定义token时,我们可以用正则表达式来描述它,因为正则表达式干这行很合适,例如一个digit+就可以描述数字,多方便。因此,我们需要根据正则表达式画出与之等价的nfa。而这个算法非常简单,就是tompson’s construction,这个书上写得很清楚了。将nfa转化成dfa(nfa的确定化)对于计算机来说,面对同一个输入,如果有多个下一状态,那计算机就不清楚要转到哪个状态,所以我们期望能从正则表达式得到dfa,而不是nfa,因为这样将来编程实现时比较(同一输入有确定的一个下一状态),而幸运的是,每个nfa都可以转化成dfa。为什么nfa 可以转化成dfa?因为fa(finite automata)中的状态都是我们自己画的,只要fa能正确的识别token,那就ok了,也就是,如果nfa和dfa都可以达到一样的效果:识别token,那其它的我们就不管了。而nfa确定化的本质,就是将原来多个状态改用一个状态来表示,新状态其实是一个状态集,比如nfa中状态s1在输入a下可以到达s2和s3,那么,在dfa中,就把s2和s3合起来认为是一个状态。还有一个问题是nfa中的空转换(?输入),如果s1在?输入下可以到达s2,就表示s1可以无条件地转移到s2,那s1和s2自然可以合并起来作为dfa中的一个状态,于是nfa转dfa的算法也就好理解了。但首先得先定义下空闭包

正则表达式7

Java正则表达式详解 仙人掌工作室 如果你曾经用过Perl或任何其他内建正则表达式支持的语言,你一定知道用正则表达式处理文本和匹配模式是多么简单。如果你不熟悉这个术语,那么“正则表达式”(Regular Expression)就是一个字符构成的串,它定义了一个用来搜索匹配字符串的模式。 许多语言,包括Perl、PHP、Python、JavaScript和JScript,都支持用正则表达式处理文本,一些文本编辑器用正则表达式实现高级“搜索-替换”功能。那么Java又怎样呢?本文写作时,一个包含了用正则表达式进行文本处理的Java规范需求(Specification Request)已经得到认可,你可以期待在JDK的下一版本中看到它。 然而,如果现在就需要使用正则表达式,又该怎么办呢?你可以从https://www.360docs.net/doc/e616874269.html,下载源代码开放的Jakarta-ORO库。本文接下来的内容先简要地介绍正则表达式的入门知识,然后以Jakarta-ORO API为例介绍如何使用正则表达式。 一、正则表达式基础知识 我们先从简单的开始。假设你要搜索一个包含字符“cat”的字符串,搜索用的正则表达式就是“cat”。如果搜索对大小写不敏感,单词“catalog”、“Catherine”、“sophisticated”都可以匹配。也就是说: 1.1句点符号 假设你在玩英文拼字游戏,想要找出三个字母的单词,而且这些单词必须以“t”字母开头,以“n”字母结束。另外,假设有一本英文字典,你可以用正则表达式搜索它的全部内容。要构造出这个正则表达式,你可以使用一个通配符——句点符号“.”。这样,完整的表达式就是“t.n”,它匹配“tan”、“ten”、“tin”和“ton”,还匹配“t#n”、“tpn”甚至“t n”,还有其他许多无意义的组合。这是因为句点符号匹配所有字符,包括空格、Tab字符甚至换行符: 1.2方括号符号 为了解决句点符号匹配范围过于广泛这一问题,你可以在方括号(“[]”)里面指定看来有意义的字符。此时,只有方括号里面指定的字符才参与匹配。也就是说,正则表达式“t[aeio]n”只匹配“tan”、“Ten”、“tin”和“ton”。但“Toon”不匹配,因为在方括号之内你只能匹配单个字符 1.3“或”符号

Java中的正则表达式+--++示例详解

Java中的正则表达式 众所周知,在程序开发中,难免会遇到需要匹配、查找、替换、判断字符串的情况发生,而这些情况有时又比较复杂,如果用纯编码方式解决,往往会浪费程序员的时间及精力。因此,学习及使用正则表达式,便成了解决这一矛盾的主要手段。 大家都知道,正则表达式是一种可以用于模式匹配和替换的规范,一个正则表达式就是由普通的字符(例如字符a到z)以及特殊字符(元字符)组成的文字模式,它用以描述在查找文字主体时待匹配的一个或多个字符串。正则表达式作为一个模板,将某个字符模式与所搜索的字符串进行匹配。 自从jdk1.4推出java.util.regex包,就为我们提供了很好的JAVA正则表达式应用平台。 因为正则表达式是一个很庞杂的体系,所以我仅例举些入门的概念,更多的请参阅相关书籍及自行摸索。 \\ 反斜杠 \t 间隔 ('\u0009') \n 换行 ('\u000A') \r 回车 ('\u000D') \d 数字等价于[0-9] \D 非数字等价于[^0-9] \s 空白符号 [\t\n\x0B\f\r] \S 非空白符号 [^\t\n\x0B\f\r] \w 单独字符 [a-zA-Z_0-9] \W 非单独字符 [^a-zA-Z_0-9] \f 换页符 \e Escape \b 一个单词的边界 \B 一个非单词的边界 \G 前一个匹配的结束 ^为限制开头 ^java 条件限制为以Java为开头字符 $为限制结尾 java$ 条件限制为以java为结尾字符 .为限制一个任意字符 java.. 条件限制为java后除换行外任意两个字符 加入特定限制条件「[]」 [a-z] 条件限制在小写a to z范围中一个字符 [A-Z] 条件限制在大写A to Z范围中一个字符 [a-zA-Z] 条件限制在小写a to z或大写A to Z范围中一个字符 [0-9] 条件限制在小写0 to 9范围中一个字符

C#正则表达式之Regex类用法详解

C#正则表达式之Regex类用法详解 正则表达式的本质是使用一系列特殊字符模式,来表示某一类字符串,正则表达式无疑是处理文本最有力的工具,而.NET提供的Regex类实现了验证正则表达式的方法。 Regex类表示不可变(只读)的正则表达式。它还包含各种静态方法,允许在不显式创建其他类的实例的情况下使用其他正则表达式类。 正则表达式基础概述 什么是正则表达式 在编写字符串的处理程序时,经常会有查找符合某些复杂规则的字符串的需要。正则表达式就是用于描述这些规则的工具。换句话说,正则表达式就是记录文本规则的代码。 通常,我们在使用WINDOWS查找文件时,会使用通配符(*和?)。如果你想查找某个目录下的所有Word文档时,你就可以使用*.doc进行查找,在这里,*就被解释为任意字符串。和通配符类似,正则表达式也是用来进行文本匹配的工具,只不过比起通配符,它能更精确地描述你的需求——当然,代价就是更复杂。 一、C#正则表达式符号模式

说明: 由于在正则表达式中“\”、“?”、“*”、“^”、“$”、“+”、“(”、“)”、“|”、“{”、“[”等字符已经具有一定特殊意义,如果需要用它们的原始意义,则应该对它进行转义,例如希望在字符串中至少有一个“\”,那么正则表达式应该这么写:\\+。

二、在C#中,要使用正则表达式类,请在源文件开头处添加以下语句: 复制代码代码如下: using Syst https://www.360docs.net/doc/e616874269.html, ressions; 三、RegEx类常用的方法 1、静态Match方法 使用静态Match方法,可以得到源中第一个匹配模式的连续子串。 静态的Match方法有2个重载,分别是 Regex.Match(string input,string pattern); Regex.Match(string input,string pattern,RegexOptions options); 第一种重载的参数表示:输入、模式 第二种重载的参数表示:输入、模式、RegexOptions枚举的“按位或”组合。 RegexOptions枚举的有效值是: Complied表示编译此模式 CultureInvariant表示不考虑文化背景 ECMAScript表示符合ECMAScript,这个值只能和IgnoreCase、Multiline、Complied连用ExplicitCapture表示只保存显式命名的组 IgnoreCase表示不区分输入的大小写 Ign https://www.360docs.net/doc/e616874269.html, pace表示去掉模式中的非转义空白,并启用由#标记的注释Multiline表示多行模式,改变元字符^和$的含义,它们可以匹配行的开头和结尾 None表示无设置,此枚举项没有意义 RightToLeft表示从右向左扫描、匹配,这时,静态的Match方法返回从右向左的第一个匹配Singleline表示单行模式,改变元字符.的意义,它可以匹配换行符

正则表达式经典教程

正则表达式是常见常忘,所以还是记下来比较保险,于是就有了这篇笔记。 希望对大家会有所帮助。J 1.什么是正则表达式 简单的说,正则表达式是一种可以用于文字模式匹配和替换的强有力的工具。是由一系列普通字符和特殊字符组成的能明确描述文本字符串的文字匹配模式。 正则表达式并非一门专用语言,但也可以看作是一种语言,它可以让用户通过使用一系列普通字符和特殊字符构建能明确描述文本字符串的匹配模式。除了简单描述这些模式之外,正则表达式解释引擎通常可用于遍历匹配,并使用模式作为分隔符来将字符串解析为子字符串,或以智能方式替换文本或重新设置文本格式。正则表达式为解决与文本处理有关的许多常见任务提供了有效而简捷的方式。 正则表达式具有两种标准: ·基本的正则表达式(BRE – Basic Regular Expressions) ·扩展的正则表达式(ERE – Extended Regular Expressions)。 ERE包括BRE功能和另外其它的概念。 正则表达式目前有两种解释引擎: ·基于字符驱动(text-directed engine) ·基于正则表达式驱动(regex-directed engine) Jeffery Friedl把它们称作DFA和NFA解释引擎。 约定: 为了描述起来方便,在本文中做一些约定: 1. 本文所举例的所有表达时都是基于NFA解释引擎的。 2. 正则表达式,也就是匹配模式,会简写为Regex。 3. Regex的匹配目标,也就是目标字符串,会简写为String。 4. 匹配结果用会用黄色底色标识。 5. 用1\+1=2 括起来的表示这是一个regex。 6. 举例会用以下格式: Regex Target String Description test This is a test 会匹配test,testcase等 2.正则表达式的起源正则表达式的?祖先?可以一直上溯至对人类神经系统如何工作的早期研究。Warren McCulloch 和 Walter Pitts 这两位神经生理学家研究出一种数学方式来描述这些神经网络。 1956 年, 一位叫 Stephen Kleene 的美国数学家在 McCulloch 和 Pitts 早期工作的基础上,发表了一篇标题为?神经网事件的表示法?的论文,引入了正则表达式的概念。正则表达式就是用来描述他称为?正则集的代数?的表达式,因此采用?正则表达式?这个术语。

相关文档
最新文档