正则表达式

正则表达式
正则表达式

1.Python正则式的基本用法

1.1基本规则

1.2重复

1.2.1最小匹配与精确匹配

1.3前向界定与后向界定

1.4组的基本知识

2.re模块的基本函数

2.1使用compile加速

2.2 match和search

2.3 finditer

2.4 字符串的修改与替换3.更深入的了解re的组与对象

3.1编译后的Pattern对象

3.2 组与Match对象

3.2.1组的名字与序号

3.2.2 Match对象的方法4.更多的资料

初学Python,对Python的文字处理能力有很深的印象,除了str对象自带

的一些方法外,就是正则表达式这个强大的模块了。但是对于初学者来说,要用好这个功能还是有点难度,我花了好长时间才摸出了点门道。由于我记性不好,很容易就忘事,所以还是写下来比较好一些,同时也可以加深印象,整理思路。

由于我是初学,所以肯定会有些错误,还望高手不吝赐教,指出我的错误。

1 Python正则式的基本用法

Python的正则表达式的模块是…re?,它的基本语法规则就是指定一个字符序列,比如你要在一个字符串s=?123abc456?中查找字符串?abc?,只要这样写:>>> import re

>>> s='123abc456eabc789'

>>>re.findall(r?abc?,s)

结果就是:

['abc', 'abc']

这里用到的函数”findall(rule , target [,flag] )”是个比较直观的函数,就是在目标字符串中查找符合规则的字符串。第一个参数是规则,第二个参数是目标字符串,后面还可以跟一个规则选项(选项功能将在compile函数的说明中详细说明)。返回结果结果是一个列表,中间存放的是符合规则的字符串。如果没有符合规则的字符串被找到,就返回一个空列表。

为什么要用r’ ..‘字符串(raw字符串)?由于正则式的规则也是由一个字符串定义的,而在正则式中

大量使用转义字符’/’,如果不用raw字符串,则在需要写一个’/’的地方,你必须得写成’//’,那么在要从目

标字符串中匹配一个’/’的时候,你就得写上4个’/’成为’////’!这当然很麻烦,也不直观,所以一般都使用r’’

来定义规则字符串。当然,某些情况下,可能不用raw字符串比较好。

以上是个最简单的例子。当然实际中这么简单的用法几乎没有意义。为了实现复杂的规则查找,re规定了若干语法规则。它们分为这么几类:功能字符:….? …*? …+? …|? …?? …^? …$? …/?等,它们有特殊的功能含义。特别是?/?字符,它是转义引导符号,跟在它后面的字符一般有特殊的含义。

规则分界符:…[… …]? …(? …)? …{… …}?等,也就是几种括号了。

预定义转义字符集:“/d”“/w” “/s”等等,它们是以字符?/?开头,后面接一个特定字符的形式,用来指示一个预定义好的含义。

其它特殊功能字符:?#? …!? …:? …-…等,它们只在特定的情况下表示特殊的含义,比如(?# …)就表示一个注释,里面的内容会被忽略。

下面来一个一个的说明这些规则的含义,不过说明的顺序并不是按照上面的顺序来的,而是我认为由浅入深,由基本到复杂的顺序来编排的。同时为了直观,在说明的过程中尽量多举些例子以方便理解。

1.1 基本规则

‘[‘‘]’字符集合设定符

首先说明一下字符集合设定的方法。由一对方括号括起来的字符,表明一个字符集合,能够匹配包含在其中的任意一个字符。比如 [abc123],表明字符?a? …b? …c? …1? …2? …3?都符合它的要求。可以被匹配。

在?[… …]?中还可以通过?-…减号来指定一个字符集合的范围,比如可以用

[a-zA-Z]来指定所以英文字母的大小写,因为英文字母是按照从小到大的顺序来排的。你不可以把大小的顺序颠倒了,比如写成[z-a]就不对了。

如果在?[… …]?里面的开头写一个…^?号,则表示取非,即在括号里的字符都不匹配。如[^a-zA-Z]表明不匹配所有英文字母。但是如果…^?不在开头,则它就不再是表示取非,而表示其本身,如[a-z^A-Z]表明匹配所有的英文字母和字符?^?。

‘|’或规则

将两个规则并列起来,以‘|’连接,表示只要满足其中之一就可以匹配。比如

[a-zA-Z]|[0-9] 表示满足数字或字母就可以匹配,这个规则等价于 [a-zA-Z0-9]注意:关于?|?要注意两点:

第一,它在?[… …]?之中不再表示或,而表示他本身的字符。如果要在?[… …]?外面表示一个?|?字符,必须用反斜杠引导,即?/|? ;

第二,它的有效范围是它两边的整条规则,比如‘dog|cat?匹配的是‘dog?和?cat?,而不是?g?和?c?。如果想限定它的有效范围,必需使用一个

无捕获组…(?: )?包起来。比如要匹配‘I have a dog?或?I have a cat?,

需要写成r?I have a (?:dog|cat)?,而不能写成r?I have a dog|cat?例

>>> s = …I have a dog , I have a cat?

>>>re.findall( r?I have a (?:dog|cat)? , s )

['I have a dog', 'I have a cat'] #正如我们所要的

下面再看看不用无捕获组会是什么后果:

>>>re.findall( r?I have a dog|cat? , s )

['I have a dog', 'cat'] #它将?I have a dog?和?cat?当成两个规则了

至于无捕获组的使用,后面将仔细说明。这里先跳过。

‘.’匹配所有字符

匹配除换行符?/n?外的所有字符。如果使用了?S?选项,匹配包括?/n?的所有字符。

例:

>>> s=?123 /n456 /n789?

>>>findall(r….+?,s)

['123', '456', '789']

>>>re.findall(r….+? , s , re.S)

['123/n456/n789']

‘^’和’$’匹配字符串开头和结尾

注意?^?不能在‘[ ]’中,否则含意就发生变化,具体请看上面的?[… …]?说明。在多行模式下,它们可以匹配每一行的行首和行尾。具体请看后面compile函数说明的?M?选项部分

‘/d’匹配数字

这是一个以?/?开头的转义字符,?/d?表示匹配一个数字,即等价于[0-9]

‘/D’匹配非数字

这个是上面的反集,即匹配一个非数字的字符,等价于[^0-9]。注意它们的大小写。下面我们还将看到Python的正则规则中很多转义字符的大小写形式,代表互补的关系。这样很好记。

‘/w’匹配字母和数字

匹配所有的英文字母和数字,即等价于[a-zA-Z0-9]。

‘/W’匹配非英文字母和数字

即?/w?的补集,等价于[^a-zA-Z0-9]。

‘/s’匹配间隔符

即匹配空格符、制表符、回车符等表示分隔意义的字符,它等价于[ /t/r/n/f/v]。(注意最前面有个空格)

‘/S’匹配非间隔符

即间隔符的补集,等价于[^ /t/r/n/f/v]

‘/A’匹配字符串开头

匹配字符串的开头。它和?^?的区别是,?/A?只匹配整个字符串的开头,即使在?M?模式下,它也不会匹配其它行的行首。

‘/Z’匹配字符串结尾

匹配字符串的结尾。它和?$?的区别是,?/Z?只匹配整个字符串的结尾,即使在?M?模式下,它也不会匹配其它各行的行尾。

例:

>>> s= '12 34/n56 78/n90'

>>>re.findall( r'^/d+' , s , re.M ) #匹配位于行首的数字

['12', '56', '90']

>>>re.findall( r?/A/d+?, s , re.M ) #匹配位于字符串开头的数字

['12']

>>>re.findall( r'/d+$' , s , re.M ) #匹配位于行尾的数字

['34', '78', '90']

>>>re.findall( r?/d+/Z? , s , re.M ) #匹配位于字符串尾的数字

['90']

‘/b’匹配单词边界

它匹配一个单词的边界,比如空格等,不过它是一个‘0’长度字符,它匹配完的字符串不会包括那个分界的字符。而如果用?/s?来匹配的话,则匹配出的字符串中会包含那个分界符。

例:

>>> s = 'abcabcdebcbcd'

>>>re.findall( r?/bbc/b? , s ) #匹配一个单独的单词…bc?,而当它是其它单词的一部分的时候不匹配

['bc'] #只找到了那个单独的?bc?

>>>re.findall( r?/sbc/s? , s )#匹配一个单独的单词…bc?

[' bc '] #只找到那个单独的?bc?,不过注意前后有两个空格,可能有点看不清楚

‘/B’匹配非边界

和?/b?相反,它只匹配非边界的字符。它同样是个0长度字符。

接上例:

>>>re.findall( r?/Bbc/w+? , s ) #匹配包含?bc?但不以?bc?为开头的单词

['bcde'] #成功匹配了?abcde?中的?bcde?,而没有匹

配?bcd?

‘(?:)’无捕获组

当你要将一部分规则作为一个整体对它进行某些操作,比如指定其重复次数时,你需要将这部分规则用?(?:? …)?把它包围起来,而不能仅仅只用一对括号,那样将得到绝对出人意料的结果。

例:匹配字符串中重复的?ab?

>>> s=?ababababbabbaabaab?

>>>re.findall( r?/b(?:ab)+/b? , s )

['ababab']

如果仅使用一对括号,看看会是什么结果:

>>>re.findall( r?/b(ab)+/b? , s )

['ab']

这是因为如果只使用一对括号,那么这就成为了一个组(group)。组的使用比较复杂,将在后面详细讲解。

‘(?# )’注释

Python允许你在正则表达式中写入注释,在?(?#? …)?之间的内容将被忽略。

(?iLmsux) 编译选项指定

Python的正则式可以指定一些选项,这个选项可以写在findall或compile的参数中,也可以写在正则式里,成为正则式的一部分。这在某些情况下会便利一些。具体的选项含义请看后面的compile函数的说明。

此处编译选项?i?等价于IGNORECASE ,L 等价于LOCAL ,m 等价

于MULTILINE ,s 等价于 DOTALL ,u 等价于UNICODE ,x 等价

于VERBOSE 。

请注意它们的大小写。在使用时可以只指定一部分,比如只指定忽略大小写,可写为…(?i)?,要同时忽略大小写并使用多行模式,可以写为…(?im)?。

另外要注意选项的有效范围是整条规则,即写在规则的任何地方,选项都会对全部整条正则式有效。

1.2 重复

正则式需要匹配不定长的字符串,那就一定需要表示重复的指示符。Python 的正则式表示重复的功能很丰富灵活。重复规则的一般的形式是在一条字符规则后面紧跟一个表示重复次数的规则,已表明需要重复前面的规则一定的次数。重复规则有:

‘*’ 0或多次匹配

表示匹配前面的规则0次或多次。

‘+’ 1次或多次匹配

表示匹配前面的规则至少1次,可以多次匹配

例:匹配以下字符串中的前一部分是字母,后一部分是数字或没有的变量名字

>>> s = … aaa bbb111 cc22cc 33dd …

>>>re.findall( r?/b[a-z]+/d*/b? , s ) #必须至少1个字母开头,以连续数字结尾或没有数字

['aaa', 'bbb111']

注意上例中规则前后加了表示单词边界的?/b?指示符,如果不加的话结果就会变成:

>>>re.findall( r?[a-z]+/d*? , s )和编译原理的正规式是差不多的

['aaa', 'bbb111', 'cc22', 'cc', 'dd'] #把单词给拆开了

大多数情况下这不是我们期望的结果。

‘?’ 0或1次匹配

只匹配前面的规则0次或1次。

例,匹配一个数字,这个数字可以是一个整数,也可以是一个科学计数法记录的数字,比如123和10e3都是正确的数字。

>>> s = … 123 10e3 20e4e4 30ee5 …

>>>re.findall( r? /b/d+[eE]?/d*/b? , s )

['123', '10e3']

它正确匹配了123和10e3,正是我们期望的。注意前后的?/b?的使用,否则将得到不期望的结果。

1.2.1 精确匹配和最小匹配

Python正则式还可以精确指定匹配的次数。指定的方式是

‘{m}’精确匹配m次

‘{m,n}’匹配最少m次,最多n次。(n>m)

如果你只想指定一个最少次数或只指定一个最多次数,你可以把另外一个参数空起来。比如你想指定最少3次,可以写成 {3,} (注意那个逗号),同样如果只想指定最大为5次,可以写成{,5},也可以写成{0,5}。

例寻找下面字符串中

a:3位数

b: 2位数到4位数

c: 5位数以上的数

d: 4位数以下的数

>>> s= … 1 22 333 4444 55555 666666 …

>>>re.findall( r?/b/d{3}/b? , s ) # a:3位数

['333']

>>>re.findall( r?/b/d{2,4}/b? , s ) # b: 2位数到4位数

['22', '333', '4444']

>>>re.findall( r?/b/d{5,}/b?, s ) # c: 5位数以上的数

['55555', '666666']

>>>re.findall( r?/b/d{1,4}/b? , s ) # 4位数以下的数

['1', '22', '333', '4444']

‘*?’ ‘+?’ ‘??’最小匹配

…*? …+? …??通常都是尽可能多的匹配字符。有时候我们希望它尽可能少的匹配。比如一个c语言的注释…/* part 1 */ /* part 2 */?,如果使用最大规则:>>> s =r …/* part 1 */ code /* part 2 */?

>>>re.findall( r?//*.*/*/? , s )

[…/* part 1 */ code /* part 2 */?]

结果把整个字符串都包括进去了。如果把规则改写成

>>>re.findall( r?//*.*?/*/? , s ) #在*后面加上?,表示尽可能少的匹配['/* part 1 */', '/* part 2 */']

结果正确的匹配出了注释里的内容

1.3 前向界定与后向界定

有时候需要匹配一个跟在特定内容后面的或者在特定内容前面的字符串,Python提供一个简便的前向界定和后向界定功能,或者叫前导指定和跟从指定功能。它们是:

‘(?<=…)’前向界定

括号中?…?代表你希望匹配的字符串的前面应该出现的字符串。

‘(?=…)’后向界定

括号中的?…?代表你希望匹配的字符串后面应该出现的字符串。

例:你希望找出c语言的注释中的内容,它们是包含在?/*?和?*/?之间,不过你并不希望匹配的结果把?/*?和?*/?也包括进来,那么你可以这样用:>>> s=r?/* comment 1 */ code /* comment 2 */?

>>>re.findall( r?(?<=//*).+?(?=/*/)? , s )

[' comment 1 ', ' comment 2 ']

注意这里我们仍然使用了最小匹配,以避免把整个字符串给匹配进去了。

要注意的是,前向界定括号中的表达式必须是常值,也即你不可以在前向界定的括号里写正则式。比如你如果在下面的字符串中想找到被字母夹在中间的数字,你不可以用前向界定:

例:

>>> s = …aaa111aaa , bbb222 , 333ccc …

>>>re.findall( r?(?<=[a-z]+)/d+(?=[a-z]+)' , s ) # 错误的用法

它会给出一个错误信息:

error: look-behind requires fixed-width pattern

不过如果你只要找出后面接着有字母的数字,你可以在后向界定写正则式:>>>re.findall( r?/d+(?=[a-z]+)?, s )

['111', '333']

如果你一定要匹配包夹在字母中间的数字,你可以使用组(group)的方式>>>re.findall (r'[a-z]+(/d+)[a-z]+' , s )

['111']

组的使用将在后面详细讲解。

除了前向界定前向界定和后向界定外,还有前向非界定和后向非界定,它的写法为:

‘(?

只有当你希望的字符串前面不是’…’的内容时才匹配

‘(?!...)’后向非界定

只有当你希望的字符串后面不跟着?…?内容时才匹配。

接上例,希望匹配后面不跟着字母的数字

>>>re.findall( r?/d+(?!/w+)?, s )

['222']

注意这里我们使用了/w而不是像上面那样用[a-z],因为如果这样写的话,结果会是:

>>>re.findall( r?/d+(?![a-z]+)? , s )

['11', '222', '33']

这和我们期望的似乎有点不一样。它的原因,是因为?111?和?222?中的前两个数字也是满足这个要求的。因此可看出,正则式的使用还是要相当小心的,因为我开始就是这样写的,看到结果后才明白过来。不过Python试验起来很方便,这也是脚本语言的一大优点,可以一步一步的试验,快速得到结果,而不用经过烦琐的编译、链接过程。也因此学习Python就要多试,跌跌撞撞的走过来,虽然曲折,却也很有乐趣。

1.4 组的基本知识

上面我们已经看过了Python的正则式的很多基本用法。不过如果仅仅是上面那些规则的话,还是有很多情况下会非常麻烦,比如上面在讲前向界定和后向界定时,取夹在字母中间的数字的例子。用前面讲过的规则都很难达到目的,但是用了组以后就很简单了。

‘(‘’)’无命名组

最基本的组是由一对圆括号括起来的正则式。比如上面匹配包夹在字母中间的数字的例子中使用的(/d+),我们再回顾一下这个例子:

>>> s = …aaa111aaa , bbb222 , 333ccc …

>>>re.findall (r'[a-z]+(/d+)[a-z]+' , s )

['111']

可以看到findall函数只返回了包含在’()’中的内容,而虽然前面和后面的内容都匹配成功了,却并不包含在结果中。

除了最基本的形式外,我们还可以给组起个名字,它的形式是

‘(?P…)’命名组

…(?P?代表这是一个Python的语法扩展?<…>?里面是你给这个组起的名字,比如你可以给一个全部由数字组成的组叫做?num?,它的形式就是?(?P/d+)?。起了名字之后,我们就可以在后面的正则式中通过名字调用这个组,它的形式是‘(?P=name)’调用已匹配的命名组

要注意,再次调用的这个组是已被匹配的组,也就是说它里面的内容是和前面命名组里的内容是一样的。

我们可以看更多的例子:请注意下面这个字符串各子串的特点。

>>> s='aaa111aaa,bbb222,333ccc,444ddd444,555eee666,fff777ggg'

我们看看下面的正则式会返回什么样的结果:

>>>re.findall( r'([a-z]+)/d+([a-z]+)' , s ) # 找出中间夹有数字的字母

[('aaa', 'aaa'), ('fff', 'ggg')]

>>>re.findall( r '(?P[a-z]+)/d+(?P=g1)' , s ) #找出被中间夹有数字的前后

同样的字母

['aaa']这个只会输出唯一的组

>>>re.findall( r'[a-z]+(/d+)([a-z]+)' , s ) #找出前面有字母引导,中间是数字,后面是字母的字符串中的中间的数字和后面的字母

[('111', 'aaa'), ('777', 'ggg')]

我们可以通过命名组的名字在后面调用已匹配的命名组,不过名字也不是必需的。

‘/number’通过序号调用已匹配的组

正则式中的每个组都有一个序号,序号是按组从左到右,从1开始的数字,你可以通过下面的形式来调用已匹配的组

比如上面找出被中间夹有数字的前后同样的字母的例子,也可以写成:

>>>re.findall( r?([a-z]+)/d+/1? , s )

['aaa']

结果是一样的。

我们再看一个例子

>>> s='111aaa222aaa111 , 333bbb444bb33'

>>>re.findall( r'(/d+)([a-z]+)(/d+)(/2)(/1)' , s ) #找出完全对称的数字-字母-数字-字母-数字中的数字和字母

[('111', 'aaa', '222', 'aaa', '111')]用组名必须和前面匹配的是一样的才可以

Python2.4以后的re模块,还加入了一个新的条件匹配功能

‘(?(id/name)yes-pattern|no-pattern)’判断指定组是否已匹配,执行相应的规则

这个规则的含义是,如果id/name指定的组在前面匹配成功了,则执行

yes-pattern的正则式,否则执行no-pattern的正则式。

举个例子,比如要匹配一些形如 usr@mail 的邮箱地址,不过有的写成

即用一对<>括起来,有点则没有,要匹配这两种情况,可以这样写>>> s=' usr2@maill2'

>>>re.findall( r'(<)?/s*(/w+@/w+)/s*(?(1)>)' , s )

[('<', 'usr1@mail1'), ('', 'usr2@maill2')]

不过如果目标字符串如下

>>> s=' usr2@maill2 < usr5@mail5 '

而你想得到要么由一对<>包围起来的一个邮件地址,要么得到一个没有被<>包围起来的地址,但不想得到一对<>中间包围的多个地址或不完整的<>中的地址,那么使用这个式子并不能得到你想要的结果

>>>re.findall( r'(<)?/s*(/w+@/w+)/s*(?(1)>)' , s )

[('<', 'usr1@mail1'), ('', 'usr2@maill2'), ('', 'usr3@mail3'), ('', 'usr4@mail4'), ('',

'usr5@mail5')]

它仍然找到了所有的邮件地址。

想要实现这个功能,单纯的使用findall有点吃力,需要使用其它的一些函数,比如match或search函数,再配合一些控制功能。这部分的内容将在下面详细讲解。

小结:以上基本上讲述了Python正则式的语法规则。虽然大部分语法规则看上去都很简单,可是稍不注意,仍然会得到与期望大相径庭的结果,所以要写好正则式,需要仔细的体会正则式规则的含义后不同规则之间细微的差别。

详细的了解了规则后,再配合后面就要介绍的功能函数,就能最大的发挥正则式的威力了。

2 re模块的基本函数

在上面的说明中,我们已经对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/7917305071.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/7917305071.html,pile(rule)

>>> compiled_rule.findall(s)

['111', '222']

可见使用compile过的规则使用和未编译的使用很相似。compile函数还可以指定一些规则标志,来指定一些特殊选项。多个选项之间用?|?(位或)连接起来。

I IGNORECASE 忽略大小写区别。

L LOCAL 字符集本地化。这个功能是为了支持多语言版本的字符集使用环境的,比如在转义符/w,在英文环境下,它代表[a-zA-Z0-9],即所以英文字符和数字。如果在一个法语环境下使用,缺省设置下,不能匹配"é" 或 "?"。加上这L选项和就可以匹配了。不过这个对于中文环境似乎没有什么用,它仍然不

能匹配中文字符。

M MULTILINE 多行匹配。在这个模式下?^?(代表字符串开头)和?$?(代表字符串结尾)将能够匹配多行的情况,成为行首和行尾标记。比如

>>> s=?123 456/n789 012/n345 678?

>>>rc=https://www.360docs.net/doc/7917305071.html,pile(r?^/d+?) #匹配一个位于开头的数字,没有使用M选项

>>>rc.findall(s)

['123'] #结果只能找到位于第一个行首的?123?

>>>rcm=https://www.360docs.net/doc/7917305071.html,pile(r?^/d+?,re.M) #使用 M 选项

>>>rcm.findall(s)

['123', '789', '345'] #找到了三个行首的数字

同样,对于?$?来说,没有使用M选项,它将匹配最后一个行尾的数字,即?678?,加上以后,就能匹配三个行尾的数字456 012和678了.

>>>rc=https://www.360docs.net/doc/7917305071.html,pile(r?/d+$?)

>>>rcm=https://www.360docs.net/doc/7917305071.html,pile(r?/d+$?,re.M)

>>>rc.findall(s)

['678']

>>>rcm.findall(s)

['456', '012', '678']

S DOTALL ….?号将匹配所有的字符。缺省情况下?.?匹配除换行符?/n?外的所有字符,使用这一选项以后,?.?就能匹配包括?/n?的任何字符了。

U UNICODE /w, /W, /b, /B, /d, /D, /s和/S都将使用Unicode。

X VERBOSE这个选项忽略规则表达式中的空白,并允许使用?#?来引导一

个注释。这样可以让你把规则写得更美观些。比如你可以把规则

>>>rc = https://www.360docs.net/doc/7917305071.html,pile(r"/d+|[a-zA-Z]+") #匹配一个数字或者单词

使用X选项写成:

>>>rc = https://www.360docs.net/doc/7917305071.html,pile(r""" # start a rule

/d+ # number

| [a-zA-Z]+ # word

""", re.VERBOSE)

在这个模式下,如果你想匹配一个空格,你必须用'/ '的形式('/'后面跟一个空格)

2.2 match与search

match( rule , targetString [,flag] )

search( rule , targetString [,flag] )

(注:re的match 与search函数同compile过的Pattern对象的match与search 函数的参数是不一样的。Pattern对象的match与search函数更为强大,是真正最常用的函数)

按照规则在目标字符串中进行匹配。

第一个参数是正则规则,第二个是目标字符串,第三个是选项(同compile 函数的选项)

返回:若成功返回一个Match对象,失败无返回

findall虽然很直观,但是在进行更复杂的操作时,就有些力不从心了。此时更多的使用的是match和search函数。他们的参数和findall是一样的,都是:match( rule , targetString [,flag] )

search( rule , targetString [,flag] )

不过它们的返回不是一个简单的字符串列表,而是一个MatchObject (如果匹配成功的话).。通过操作这个matchObject,我们可以得到更多的信息。

需要注意的是,如果匹配不成功,它们则返回一个NoneType。所以在对匹配完的结果进行操作之前,你必需先判断一下是否匹配成功了,比如:>>> m=re.match( rule , target )

>>> if m: #必需先判断是否成功

doSomethin

这两个函数唯一的区别是:match从字符串的开头开始匹配,如果开头位置没有匹配成功,就算失败了;而search会跳过开头,继续向后寻找是否有匹配的字符串。针对不同的需要,可以灵活使用这两个函数。

关于match返回的MatchObject如果使用的问题,是Python正则式的精髓所在,它与组的使用密切相关。我将在下一部分详细讲解,这里只举个最简单的例子:

例:

>>> s= 'Tom:9527 , Sharry:0003'

>>> m=re.match( r'(?P/w+):(?P/d+)' , s )

>>>m.group()

'Tom:9527'

>>>m.groups()

('Tom', '9527')

>>>m.group(…name?)

'Tom'

>>>m.group(…num?)

'9527'

2.3 finditer

finditer( rule , target [,flag] )

参数同findall

返回一个迭代器

finditer函数和findall函数的区别是,findall返回所有匹配的字符串,并存为一个列表,而finditer则并不直接返回这些字符串,而是返回一个迭代器。关于迭代器,解释起来有点复杂,还是看看例子把:

>>> s=?111 222 333 444?

>>> for i in re.finditer(r?/d+? , s ):

print i.group(),i.span() #打印每次得到的字符串和起始结束位置

结果是

111 (0, 3)

222 (4, 7)

333 (8, 11)

444 (12, 15)

简单的说吧,就是finditer返回了一个可调用的对象,使用 for i in finditer()的形式,可以一个一个的得到匹配返回的Match对象。这在对每次返回的对象进行比较复杂的操作时比较有用。

2.4 字符串的替换和修改

re模块还提供了对字符串的替换和修改函数,他们比字符串对象提供的函数功能要强大一些。这几个函数是

sub ( rule , replace , target [,count] )

subn(rule , replace , target [,count] )

在目标字符串中规格规则查找匹配的字符串,再把它们替换成指定的字符串。你可以指定一个最多替换次数,否则将替换所有的匹配到的字符串。

第一个参数是正则规则,第二个参数是指定的用来替换的字符串,第三个参数是目标字符串,第四个参数是最多替换次数。

这两个函数的唯一区别是返回值。

sub返回一个被替换的字符串

sub返回一个元组,第一个元素是被替换的字符串,第二个元素是一个数字,表明产生了多少次替换。

例,将下面字符串中的?dog?全部替换成?cat?

>>> s=? I have a dog , you have a dog , he have a dog …

>>>re.sub( r?dog? , …cat? , s )

' I have a cat , you have a cat , he have a cat '

如果我们只想替换前面两个,则

>>>re.sub( r?dog? , …cat? , s , 2 )

' I have a cat , you have a cat , he have a dog '

或者我们想知道发生了多少次替换,则可以使用subn

>>>re.subn( r?dog? , …cat? , s )

(' I have a cat , you have a cat , he have a cat ', 3)

split( rule , target [,maxsplit] )

切片函数。使用指定的正则规则在目标字符串中查找匹配的字符串,用它们作为分界,把字符串切片。

第一个参数是正则规则,第二个参数是目标字符串,第三个参数是最多切片次数

返回一个被切完的子字符串的列表

这个函数和str对象提供的split函数很相似。举个例子,我们想把上例中的字符串被?,?分割开,同时要去掉逗号前后的空格

>>> s=? I have a dog , you have a dog , he have a dog …

>>>re.split( …/s*,/s*? , s )

[' I have a dog', 'you have a dog', 'he have a dog ']

结果很好。如果使用str对象的split函数,则由于我们不知道?,?两边会有多少个空格,而不得不对结果再进行一次处理。

escape( string )

这是个功能比较古怪的函数,它的作用是将字符串中的non-alphanumerics字符(我已不知道该怎么翻译比较好了)用反义字符的形式显示出来。有时候你可能希望在正则式中匹配一个字符串,不过里面含有很多re使用的符号,你要一个一个的修改写法实在有点麻烦,你可以使用这个函数,

例在目标字符串s中匹配?(*+?)?这个子字符串

>>> s= …111 222 (*+?) 333?

>>> rule= re.escape( r?(*+?)? )

>>> print rule

/(/*/+/?/)

>>>re.findall( rule , s )

['(*+?)']

3 更深入的了解re的组与对象

前面对Python正则式的组进行了一些简单的介绍,由于还没有介绍到match 对象,而组又是和match对象密切相关的,所以必须将它们结合起来介绍才能充分地说明它们的用途。

不过再详细介绍它们之前,我觉得有必要先介绍一下将规则编译后的生成的patter对象

3.1编译后的Pattern对象

将一个正则式,使用compile函数编译,不仅是为了提高匹配的速度,同时还能使用一些附加的功能。编译后的结果生成一个Pattern对象,这个对象里面有很多函数,他们看起来和re模块的函数非常象,它同样有findall , match , search ,finditer , sub , subn , split 这些函数,只不过它们的参数有些小小的不同。一般说来,re模块函数的第一个参数,即正则规则不再需要了,应为规则就包含在Pattern对象中了,编译选项也不再需要了,因为已经被编译过了。因此re模块中函数的这两个参数的位置,就被后面的参数取代了。

findall , match , search 和finditer这几个函数的参数是一样的,除了少了规则和选项两个参数外,它们又加入了另外两个参数,它们是:查找开始位置和查找结束位置,也就是说,现在你可以指定查找的区间,除去你不感兴趣的区间。它们现在的参数形式是:

findall ( targetString [, startPos [,endPos] ] )

finditer ( targetString [, startPos [,endPos] ] )

match ( targetString [, startPos [,endPos] ] )

search ( targetString [, startPos [,endPos] ] )

这些函数的使用和re模块的同名函数使用完全一样。所以就不多介绍了。

除了和re模块的函数同样的函数外,Pattern对象还多了些东西,它们是:flags 查询编译时的选项

pattern 查询编译时的规则

groupindex 规则里的组

这几个不是函数,而是一个值。它们提供你一些规则的信息。比如下面这个例子

>>>

p=https://www.360docs.net/doc/7917305071.html,pile( r'(?P/b[a-z]+/b)|(?P/b/d+/b)|(?P/b[a-z_]+/w*/b)' , re.I )

正则表达式

正则表达式 一、什么是这则表达式 正则表达式(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/7917305071.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"); } } } }

word文档中批量删除英文或者中文、标点的方法

删除英文方法: 按ctrl+H查找替换就可以了!在查找内容中输入^$替换为^p,点“全部替换”,这时所有的英文都会被删除了,并且会自动换行出来! 删除汉字和中文标点: 同上在查找内容输入“[!^1-^127]”(输入引号之间的内容,这表示所有非西文字符,即所有汉字和中文标点符号)。替换内容什么也不要输入,点全部替换。 删除汉字: 用Ctrl+H打开查找和替换,高级选项里的“使用通配符”要记得选上。 输入查找内容“[一-龥]”(输入引号之间的内容,这表示所有的中文汉字),替换内容什么也不要输入,即删除所有查找内容。 删除汉字和中文标点: 同上在查找内容输入“[!^1-^127]”(输入引号之间的内容,这表示所有非西文字符,即所有汉字和中文标点符号),这个就有点正则表达式的意思了。 替换内容什么也不要输入。 ================= 请用查找替换法,在钩选通配符下: [^1-^127]所有西文 [!^1-^127]所有西文以外字符 Word小技巧: 仅删除文件里的中文或英文

如果我们在一份混杂着全角与半角的中英文、数字和符号的文件中,只想单独删除里头的英文字或中文字时,除了一个字删除之外,有什么比较快速简便的方法吗? 1.首先开启我们想处理的文件,其中包含全角与半角的中英文、数字和符号,并点选菜单【编辑】→【取代】。 ※[ ]里的「^1-^127」表示ASCII字码的编号1至127,其中编号48~57代表数字「0~9」,65~90代表大写英文字母「A~Z」,97~122代表小写英文字母「a~z」。 2.在「寻找及取代」对话盒中的「寻找目标」输入「[^1-^127]」,接着点选〔更多〕后,勾选「使用万用字符」,并按下〔全部取代〕。 3.此时可以看到文件中所有半角的英文字、数字及符号,全都删除掉了。 ※由于中文字都是全角,没有半角的,因此不会受影响。 4.不存盘关闭档案并重新开启后,这次在「寻找及取代」对话盒中的「寻找目标」输入「[!^1-^127]」,并在点选〔更多〕后勾选「使用万用字符」,按下〔全部取代〕。 5.可以发现这次是把全角的中英文、数字及符号,全都删除掉,只剩下半角的部分。

find与grep命令简介及正则表达式

find与grep命令简介及正则表达式写给大家看的Shell脚本编程入门教程索引 两个更为有用的命令和正则表达式 在我们开始学习新的Shell编程知识之前,我们先来看一下两个更为有用的两个命令,这两个命令虽然并不是Shell的一部分,但是在进行Shell编程时却会经常用到.随后我们会来看一下正则表达式. find命令 我们先来看的是find命令.这个命令对于我们用来查找文件时是相当有用的,但是对于Linux新手来说却有一些难于使用,在一定程序是由于他所带的选项,测试,动作类型参数,而且一个参数的执行结果会影响接下来的参数. 在我们深入这些选项和参数之前,我们先来看一个非常简单的例子.假如在我们的机子上有一个文件wish.我们来进行这个操作时要以root身份来运行,这样就可以保证我们可以搜索整个机子: #find/-name wish-print /usr/bin/wish # 正如我们可以想到的,他会打印出搜索到的结果.很简单,是不是? 然而,他却需要一定的时间来运行,因为他也会同时搜索网络上的Window机器上的磁盘.Linux机器会挂载大块的Window机器的文件系统.他也会同时那些位置,虽然我们知道我们要查找的文件位于Linux机器上. 这也正是第一个选项的用武之地.如果我们指定了-mount选项,我们就可以告诉find命令不要搜索挂载的目录.

#find/-mount-name wish-print /usr/bin/wish # 这样我们仍然可以搜索这个文件,但是这一次并没有搜索挂载的文件系统. find命令的完整语法如下: find[path][options][tests][actions] path是一个很简单的部分:我们可以使用绝对路径,例如/bin,或者是使用相对路径,例如..如果我们需要我们还可以指定多个路径,例如find/var/home 主要的一些选项如下: -depth在查看目录本身以前要先搜索目录中的内容 -follow跟随符号链接 -maxdepths N在搜索一个目录时至多搜索N层 -mount(或-xdev)不要搜索其他的文件系统 下面的是一些test的选项.我们可以为find命令指定大量的测试,并且每一个测试会返回真或是假.当find命令工作时,他会考查顺序查找到的文件,并且会在这个文件上按顺序进行他们所定义的测试.如果一个测试返回假,find命令会停止他当前正在考查的文件并继续进行下面的动作.我们在下表中列出的只是一些我们最常用到的测试,我们可以通过查看手册页得到我们可以利用find 命令使用的可能的扩展列表项. -atime NN天以前访问的文件 -mtime NN天以前修改的文件

正则表达式经典手册

引言 正则表达式(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 简单的转义字符 一些不便书写的字符,采用在前面加 "\" 的方法。这些字符其实我们都已经熟知了。

正则表达式1

正则表达式 7.1、在JavaScript中,正则表达式是对Perl版的改进和发展。 7.2、^表示一个字符串的开始,$表示一个字符串的结束。 7.3、(?:...)表示一个非捕获型分组(noncapturing group)。 7.4、(...)表示一个捕获型分组(capturing group)。 7.5、[...]表示一个字符类,[^?#]表示一个字符类包含除?和#之外的所有字符。 7.6、有两个方法来创建RegExp对象。优先采用正则表达式字面量。如下: var my_regexp=/"(?:\\.|[^\\\"])*"/g;但如果要使用RegExp构造器创建一个正则表达式,要多加小心,因为反斜杠在正则表达式和在字符串字面量中有不同的含义。通常需要双写反斜杠及对引号进行转义: var my_regexp=new RegExp("\"(?:\\.|[^\\\\\\\"])*\"",'g');7.7、在RegExp中,有三个标志:g、i和m。 7.8、RegExp对象的属性 属性用法 global如果标志g被使用,值为true ignoreCase如果标志i被使用,值为true lastIndex下一次exec匹配开始的索引。初始值为0 multiline如果m被使用,值为true source正则表达式源代码文本 7.9、一个正则表达式因子可以是一个字符、一个由圆括号包围的组、一个字符类,或者是一个转义序列。除了控制字符和特殊字符以外,所有的字符都将被按照字面处理:\/[](){}?+*|.^$ 如果上面列出的字符按字面去【匹配,那么必须要一个\前缀来进行转移。 7.10、正则表达式转义: \f是换页符,\n是换行符,\r是回车符,\t是制表符,\u允许指定一个Unicode字符来表示一个十六进制的常量 \d等同于[0-9] \s等同于[\f\n\r\t\u000B\u0020\u00A0\u2028\u2029]。这是Unicode空白符的一个不完全子集。\S表示与其相反的:[^\f\n\r\t\u000B\u0020\u00A0\u2028\u2029] \w等同于[0-9A-Z_a-z]。\W则表示与其相反。 \b被指定为一个字的边界标志。 \1是指分组1所捕获到的文本的一个引用,\2指向分组2的引用,\3指向分组3的引用,以此类推。 7.11、正则表达式分组共有4种:捕获型、非捕获型、向前正向匹配和向前负向匹配。7.12、正则表达式字符类内部的转义规则和正则表达式因子相比稍有不同。[\b]是退格符。下面是在字符类中需要被转义的特殊字符: -/[\]^ 7.13、正则表达式因子可以用一个正则表达式量词后缀,用来决定这个因子应该被匹配的次数。包围在一对花括号中的一个数字表示这个因子应该被匹配的次数。所以,/www/和/w{3}/等价。{3,6}将【匹配3、4、5或6次。{3,}匹配3次或更多次。 7.14、?等同于{0,1}。*等同于{0,}+则等同于{1,}。 7.15、如果只有一个量词,则趋向于进行贪婪性的匹配,即匹配尽可能多的重复直至达到上限。如果这个量词还有一个额外的后缀?,那么则趋向于进行懒惰性匹配,即试图匹配尽可

中文文本挖掘预处理流程总结

中文文本挖掘预处理流程总结 2017-09-22 12:14 编程派 0 0 阅读 15 作者:刘建平 来源:https://www.360docs.net/doc/7917305071.html,/pinard/p/6744056.html 在对文本做数据分析时,我们一大半的时间都会花在文本预处理上,而中文和英文的预处理流程稍有不同,本文就对中文文本挖掘的预处理流程做一个总结。 1. 中文文本挖掘预处理特点 首先我们看看中文文本挖掘预处理和英文文本挖掘预处理相比的一些特殊点。 首先,中文文本是没有像英文的单词空格那样隔开的,因此不能直接像英文一样可以直接用最简单的空格和标点符号完成分词。所以一般我们需要用分词算法来完成分词,在文本挖掘的分词原理中,我们已经讲到了中文的分词原理,这里就不多说。 第二,中文的编码不是utf8,而是unicode。这样会导致在分词的时候,和英文相比,我们要处理编码的问题。 这两点构成了中文分词相比英文分词的一些不同点,后面我们也会重点讲述这部分的处理。当然,英文分词也有自己的烦恼,这个我们在以后再讲。了解了中文预处理的一些特点后,我们就言归正传,通过实践总结下中文文本挖掘预处理流程。 2. 中文文本挖掘预处理一:数据收集 在文本挖掘之前,我们需要得到文本数据,文本数据的获取方法一般有两种:使用别人做好的语料库和自己用爬虫去在网上去爬自己的语料数据。 对于第一种方法,常用的文本语料库在网上有很多,如果大家只是学习,则可以直接下载下来使用,但如果是某些特殊主题的语料库,比如"机器学习"相关的语料库,则这种方法行不通,需要我们自己用第

对于第二种使用爬虫的方法,开源工具有很多,通用的爬虫我一般使用beautifulsoup。但是我们我们需要某些特殊的语料数据,比如上面提到的"机器学习"相关的语料库,则需要用主题爬虫(也叫聚焦爬虫)来完成。这个我一般使用ache。 ache允许我们用关键字或者一个分类算法来过滤出我们需要的主题语料,比较强大。 3. 中文文本挖掘预处理二:除去数据中非文本部分 这一步主要是针对我们用爬虫收集的语料数据,由于爬下来的内容中有很多html的一些标签,需要去掉。少量的非文本内容的可以直接用Python的正则表达式(re)删除, 复杂的则可以用beautifulsoup来去除。去除掉这些非文本的内容后,我们就可以进行真正的文本预处理了。 4. 中文文本挖掘预处理三:处理中文编码问题 由于Python2不支持unicode的处理,因此我们使用Python2做中文文本预处理时需要遵循的原则是,存储数据都用utf8,读出来进行中文相关处理时,使用GBK之类的中文编码,在下面一节的分词时,我们再用例子说明这个问题。 5. 中文文本挖掘预处理四:中文分词 常用的中文分词软件有很多,个人比较推荐结巴分词。安装也很简单,比如基于Python的,用"pip install jieba"就可以完成。下面我们就用例子来看看如何中文分词。 首先我们准备了两段文本,这两段文本在两个文件中。两段文本的内容分别是nlp test0.txt和 nlp test2.txt: 1. 沙瑞金赞叹易学习的胸怀,是金山的百姓有福,可是这件事对李达康的触动很大。易学习又回忆起他们三人分开的前一晚,大家一起喝酒话别,易 学习被降职到道口县当县长,王大路下海经商,李达康连连赔礼道歉,觉得对不起大家,他最对不起的是王大路,就和易学习一起给王大路凑了5万块钱,王大路自己东挪西撮了5万块,开始下海经商。没想到后来王大路竟然做得风生水起。沙瑞金觉得他们三人,在困难时期还能以沫相助,很不容易。 沙瑞金向毛娅打听他们家在京州的别墅,毛娅笑着说,王大路事业有成之后,要给欧阳菁和她公司的股权,她们没有要,王大路就在京州帝豪园买了三套别墅,可是李达康和易学习都不要,这些房子都在王

awk正则表达式介绍

awk命令详解 简单使用: awk :对于文件中一行行的独处来执行操作。 awk -F :'{print $1,$4}' :使用‘:’来分割这一行,把这一行的第一第四个域打印出来。 详细介绍: AWK命令介绍 awk语言的最基本功能是在文件或字符串中基于指定规则浏览和抽取信息,awk抽取信息 后,才能进行其他文本操作,完整的awk脚本通常用来格式化文本文件中的信息 1.调用awk: 第一种命令行方式,如: awk [-Field-separator] 'commands' input-file(s) 这里commands是真正的awk命令,[-F域分隔符]是可选的,awk默认使用空格分隔, 因此如果要浏览域间有空格的文本,不必指定这个选项,但如果浏览如passwd文件,此文件 各域使用冒号作为分隔符,则必须使用-F选项: awk -F : 'commands' input-file 第二种,将所有awk命令插入一个文件,并使awk程序可执行,然后用awk命令解释器作为脚 本的首行,以便通过键入脚本名称来调用它 第三种,将所有awk命令插入一个单独文件,然后调用,如: awk -f awk-script-file input-file -f选项指明在文件awk-script-file的awk脚本,input-file是使用awk进行浏览 的文件名 2.awk脚本: awk脚本由各种操作和模式组成,根据分隔符(-F选项),默认为空格,读取的内容依次放置到 对应的域中,一行一行记录读取,直到文件尾 2.1.模式和动作

任何awk语句都是由模式和动作组成,在一个awk脚本中可能有许多语句。模式部分决定动作语句何时触发及触发事件。动作即对数据进行的操作,如果省去模式部分,动作将时刻保持执行状态 模式可以是任何条件语句或复合语句或正则表达式,模式包含两个特殊字段BEGIN和END,使用BEGIN语句设置计数和打印头,BEGIN语句使用在任何文本浏览动作之前,之后文本浏览动作依据输入文件开始执行;END语句用来在awk完成文本浏览动作后打印输出文本总数和结尾状态标志,有动作必须使用{}括起来 实际动作在大括号{}内指明,常用来做打印动作,但是还有更长的代码如if和循环looping 语句及循环退出等,如果不指明采取什么动作,awk默认打印出所有浏览出的记录 2.2.域和记录: awk执行时,其浏览标记为$1,$2...$n,这种方法称为域标记。使用$1,$3表示参照第1和第3域,注意这里使用逗号分隔域,使用$0表示使用所有域。例如: awk '{print $0}' temp.txt > sav.txt 表示打印所有域并把结果重定向到sav.txt中 awk '{print $0}' temp.txt|tee sav.txt 和上例相似,不同的是将在屏幕上显示出来 awk '{print $1,$4}' temp.txt 只打印出第1和第4域 awk 'BEGIN {print "NAME GRADE\n----"} {print $1"\t"$4}' temp.txt 表示打信息头,即输入的内容的第一行前加上"NAME GRADE\n-------------",同时内容以tab分开 awk 'BEGIN {print "being"} {print $1} END {print "end"}' temp 同时打印信息头和信息尾 2.3.条件操作符: <、<=、==、!=、>=、~匹配正则表达式、!~不匹配正则表达式

正则表达式语法完整版

正则表达式基础知识 一个正则表达式就是由普通字符(例如字符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]%"表 示两个百分号中不应该出现字母)。 为了逐字表达,必须在"^.$()|*+?{\"这些字符前加上转移字符'\'。 请注意在方括号中,不需要转义字符。

Delphi 正则表达式

Delphi 正则表达式语法(1): 关于大小写与中文 //替换一般字符串 var reg: TPerlRegEx; begin reg := TPerlRegEx.Create(nil); reg.Subject := '我爱DELPHI, 但Delphi不爱我!'; reg.RegEx := 'Delphi'; reg.Replacement := '◆'; reg.ReplaceAll; ShowMessage(reg.Subject); //返回: 我爱DELPHI, 但◆不爱我! FreeAndNil(reg); end; //不区分大小写 var reg: TPerlRegEx; begin reg := TPerlRegEx.Create(nil); reg.Subject := '我爱DELPHI, 但Delphi不爱我!'; reg.RegEx := 'Delphi'; reg.Replacement := '◆'; reg.Options := [preCaseLess]; //不区分大小的设定, 默认是区分的 reg.ReplaceAll; ShowMessage(reg.Subject); //返回: 我爱◆, 但◆不爱我! FreeAndNil(reg);

reg.ReplaceAll; ShowMessage(reg.Subject); //返回: ◆◆DELPHI, ◆Delphi◆◆◆! FreeAndNil(reg); end; //我测试了不同的汉字, 除了乱以外,没有规律; 所有如果操作汉字暂时不要指定 preCaseLess Delphi 正则表达式语法(2): 或者与重复 // | 号的使用, | 是或者的意思 var reg: TPerlRegEx; begin reg := TPerlRegEx.Create(nil); reg.Subject := 'CodeGear Delphi 2007'; reg.RegEx := 'e|Delphi|0'; //使用了 | 记号 reg.Replacement := '◆'; reg.ReplaceAll; ShowMessage(reg.Subject); //返回: Cod◆G◆ar ◆ 2◆◆7 FreeAndNil(reg); end; // + 的使用, + 是重复 1 个或多个 var reg: TPerlRegEx; begin reg := TPerlRegEx.Create(nil);

正则表达式

多少年来,许多的编程语言和工具都包含对正则表达式的支持,.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:不对字符串中的转义字符转义。

[VIP专享]经典正则表达式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}|1dd|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

Excel中使用正则表达式

Excel另类条件化格式 1 前言 我们知道,Excel的条件化格式可以根据单元个的内容来设置整个单元格的格式。如图1中的C列,当单元格的内容为“结束”时,字体颜色为绿色,为“进行中”时,颜色为黄色。但如果我们想把B列的部分特定文字(如日期2012-3-4)设置成不同的字体和颜色, Excel的条件化格式工具是不能实现的,需要另辟蹊径。 图1 2 实现过程 2.1 目标 实现B列单元格中日期字符串的字体设置成“Arial Black”字体,颜色为红色。 2.2 设计思路 Excel的VBA编程功能很强大,可以轻松实现上述目标。程序的设计思路是:找到日期字符串,然后设置字体格式。本例中利用了正则表达式来寻找日期字符串,通过Characters对象的Font属性来设置字符串的格式。 2.3 正则表达式 我们在处理文本时,经常会遇到一些满足某种规则的字符串。比如,一个无符号的整数由一连串的数字构成,本例中的日期是满足“整数-整数-整数”规则的字符串。正则表达式就是用来指定这种规则的。如果某个字符串满足正则表达式指定的规则,则称该字符串为正则表达式的一个“匹配串”。正则表达式中用\d 来匹配单个数字,用\d+来匹配连续的多个数字,这样本例中用"\d+-\d+-\d+"就可以匹配日期字符串。Excel的VBA可以通过引用vbscript中的正则标定式对象"vbscript.regexp"来使用正则表达式。 2.4 Characters函数 语法:Characters(start, length) 参数:Start是指从第几个字符处开始选择,length是要返回的字符数。 返回:Characters对象。用来控件文本中某一范围的字符串。例如,通过Characters对象的Font属性可以设置字符串的字体格式。 2.5程序代码 把FormatClick程序和“更新”按钮的Click事件关联起来,只要点击“更新”按钮就可以更新日期的字体的名称和颜色了。具体程序如下: Sub FormatClick() '声明正则表达式对象 Dim RegEx As Object '引用正则标定式对象 Set RegEx = CreateObject("vbscript.regexp")

sed_4.2.1_man_中文

本文参照sed 4.2.1的man原文翻译。蓝色字体为man原文,黑色字体是我的译文。 水平有限,难免错漏,欢迎各位指正! GNU文档的精髓在info页,而不是man页。 当然更希望有同仁将sed的info页翻译出来,方便大家更扎实地运用好sed这个功能强大的工具。 翻译者:李启训。 NAME 名称 sed - stream editor for filtering and transforming text 用于过滤和转换文本的流编辑器。 SYNOPSIS 提要 sed [OPTION]... {script-only-if-no-other-script} [input-file]... DESCRIPTION 描述 Sed is a stream editor. A stream editor is used to perform basic text transformations on an input stream (a file or input from a pipeline). While in some ways similar to an editor which permits scripted edits (such as ed), sed works by making only one pass over the input(s), and is consequently more efficient. But it is sed's ability to filter text in a pipeline which particularly distinguishes it from other types of editors. Sed 是一个流编辑器。流编辑器用于转换输入流(文件或者来自管道)的基本文本。虽然在某些方面它类似于允许脚本编辑的编辑器(比如ed),但是sed只对一次传递的输入进行操作,当然更加高效。除此以外,因为sed能够过滤来自管道中的文本,这明显区别于其他类型的编辑器。 -n, --quiet, --silent suppress automatic printing of pattern space 抑制模式空间的自动输出。 -e script, --expression=script add the script to the commands to be executed 添加脚本给命令,以便执行。 -f script-file, --file=script-file add the contents of script-file to the commands to be executed 添加脚本文件的内容,以便执行。 --follow-symlinks follow symlinks when processing in place 就地处理时跟随符号链接。 -i[SUFFIX], --in-place[=SUFFIX] edit files in place (makes backup if extension supplied) 就地编辑文件(如果提供扩展,则备份文件)。 -l N, --line-length=N specify the desired line-wrap length for the `l' command 为l命令指定所预期的行的长度。 --posix disable all GNU extensions. 禁用所有GNU扩展。 -r, --regexp-extended use extended regular expressions in the script. 在脚本中使用扩展正则表达式。 -s, --separate consider files as separate rather than as a single continuous

语法词法生成器

语法词法生成器 一、语法词法生成器Flex 语法扫描器生成器 flex (fast lexical analyser generator) 是Lex的另一个替代品。它经常和自由软件Bison语法分析器生成器一起使用。Flex 最初由Vern Paxson 于1987 年用C语言写成。语法分析生成器JavaCC JavaCC(Java Compiler Compiler) 是一个用JA V A开发的最受欢迎的语法分析生成器。这个分析生成器工具可以读取上下文无关且有着特殊意义的语法并把它转换成可以识别且匹 配该语法的JA VA程序。它还提供JJTree等工具来...语法分析器生成工具YACC 这是一个经典的生成语法分析器的工具,大学的《编译原理》课程里介绍过。词法分析工具ANTLR ANTLR(ANother Tool for Language Recognition)它是Java开发的词法分析工具,它可以接受词文法语言描述,并能产生识别这些语言的语句的程序。作为翻译程序的一部分,你可以使用简单的操作符和动作来参数化你的文法...解析器生成器

Bison GNU bison是一个自由软件,用于自动生成语法分析器程序,实际上可用于所有常见的操作系统。Bison把LALR形式的上下文无关文法描述转换为可做语法分析的C或C++程序。在新近版本中,Bison增加了对GLR语法分析算法的支...词法分析器生成工具Lex 这是一个经典的生成词法分析器的工具语法分析器生成工 具Berkeley Yacc Berkeley Yacc (byacc) 是一个高质量的yacc 变种,其目的是为了避免依赖某个特定的编译器。语法分析生成器JFlex JFlex是一个Java的词法/语法分析生成器。JavaScript解析器Jison JavaScript解析器,Coffee就是使用Jison解析的。Jison 将一个上下文无关语法作为输入,输出对应的JavaScript代码,类似Yacc。词法/语法分析框架chrysanthemum chrysanthemum (中文名“菊花”)是一个由C++写成的小巧

PHP 常用正则表达式 正则

PHP 常用正则表达式正则 平时做网站经常要用正则表达式,下面是一些讲解和例子,仅供大家参考和修改使用:"^\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})(]?)$" //Emil /^((\+?[0-9]{2,4}\-[0-9]{3,4}\-)|([0-9]{3,4}\-))?([0-9]{7,8})(\-[0-9]+)?$/ //电话号码 "^(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}|1dd|2[0-4]d|25[0-5]).(d{1,2}| 1dd|2[0-4]d|25[0-5])$" //IP地址 匹配中文字符的正则表达式:[\u4e00-\u9fa5] 匹配双字节字符(包括汉字在内):[^\x00-\xff] 匹配空行的正则表达式:\n[\s| ]*\r 匹配HTML标记的正则表达式:/<(.*)>.*<\/\1>|<(.*) \/>/ 匹配首尾空格的正则表达式:(^\s*)|(\s*$) 匹配Email地址的正则表达式:\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)* 匹配网址URL的正则表达式:^[a-zA-z]+://(\\w+(-\\w+)*)(\\.(\\w+(-\\w+)*))*(\\?\\S*)?$ 匹配帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线):^[a-zA-Z][a-zA-Z0-9_]{4,15}$ 匹配国内电话号码:(\d{3}-|\d{4}-)?(\d{8}|\d{7})? 匹配腾讯QQ号:^[1-9]*[1-9][0-9]*$ 元字符及其在正则表达式上下文中的行为: \ 将下一个字符标记为一个特殊字符、或一个原义字符、或一个后向引用、或一个八进制转

相关文档
最新文档