正则表达式


字符串是编程时遇到最多的一种数据结构,对字符串的操作无所不在。比如判断一个字符串是否是合法的email地址,虽然编程可以取@前后的字符串,再分别判断是否是单词和域名,但这样做非常麻烦,而且代码很难复用。

正则表达式是一种用来匹配字符串的强有力工具。它的设计思想是一用一种描述性语言给字符串定义一个规则,凡是符合规则的字符串,我们就认为它匹配了,否则该字符串就是不合法的。

所以,我们判断一个字符串是否是合法email的方法:
1、创建一个匹配email的正则表达式。

2、用该正则表达式匹配用户的输入是否合法。

因为正则表达式也是用字符串表示的,所以,我们首先了解如何用字符表示字符。

在正则表达式中,如果直接给出字符,就是精确匹配。用\d匹配数字,用\w匹配一个字母或数字,所以:
'00\d' 可以匹配到'007',但是无法匹配到'00p'

'\w\w\d'可以匹配到'py3'

.可以匹配任意字符,所以:
'py.'可以匹配'pyc' 'pyo' 'py!'等等。

要匹配变长的字符,在正则表达式中,用*表示任意个字符(包括0个),用+表示至少一个字符,用?表示0个或1个字符,用{n}表示n个字符。用{n-m}表示n-m个字符:
来看一个复杂的例子:
\d{3}\s+\d{3-8}

\s可以匹配一个空格(也包括Tab等空白符),所以\s+表示至少一个空格,例如匹配' ',' '等。

\d{3-8}表示3-8个数字,例如:'12345678'

综合起来,上面的正则表达式可以任意匹配以任意空格隔开的电话号码。

如果要匹配'010-345678'这样的电话号码呢?因为'-'是特殊字符,在正则表达式中需要使用'\'转义,所以: \d{3}\-\d{3-8}

但是仍然无法匹配'010 - 3456'这样的电话号码,因为带有空格,所以需要更复杂的正则表达式。


进阶


如果要精确的匹配,可以用[]表示范围,比如:

[0-9a-zA-Z\_]可以匹配一个数字字母或下划线。

[0-9a-zA-Z\_]+可以匹配至少由一个数字、字母、或下划线组成的字符串。比如'a100','0_z','py300'

[a-zA-Z\_][0-9a-zA-Z\_]*可以匹配由字母或下划线开头,后接任意个由字母数字或下划线组成的字符串,也就是python的合法变量。

[a-zA-Z\_][0-9a-zA-Z\_]{0,19}更精确的限制了变量的长度是1-20个字符(前面一个字符+后面最多19个字符)

A|B可以匹配A或B,所以[P|python]可以匹配'Python'或者'python'

^表示行的开头,^\d表示必须以数字开头。

$表示行的结束,\d$表示必须以数字结束。

你可能注意到了,py也可以匹配‘python’,但是加上^py$,这样就只能匹配'py'了。


re模块

有了准备知识,我们就可以在Python中使用正则表达式了。Python提供re模块,包含所有正则表达式功能。由于Python本省的字符串也使用\转义,以下要特别注意:
s ='abc\\-001' #Python的字符串

转义之后:'abc\-001'

因此,我们强烈推荐使用python的r前缀,就不用考虑转义的问题了:
s =r'abc\-001'

转义后:'abc\-001'

先看看如何判断正则表达式是否匹配:
>>>import re

>>>re.match(r'^\d{3}\-\d{3,8}$','010-12345')

<_sre.SRE_Match object; span=(0,9),match='010-12345'>

>>>re.match(r'^\d{3}\-\d{3,'010 12345')

>>>

可以看出,match()方法如果匹配,则返回一个Match对象,否则返回None。常见的判断方法:
test ='用户输入的字符串'

if re.match(r'正则表达式',test):

print('ok')

else:
print('Failed')


切分字符串

用正则表达式切分字符串比使用固定的字符串更灵活,请看正常的切分代码:
>>>'ab c'.split(' ')

['a','b','','c']

无法识别连续的空格,用正则表达式试试:
>>>re.split(r'\s+','ab c')

['a','c']

无论多少个空格都可以正常分割,加入,试试:
>>>re.split(r'[\s\,]+','a,bc,d')

['a','c','d']

再加入;试试:
>>>re.mathch(r'[\s\,\;]+',;b;c ;;d')

['a','d']

如果用户输入了一组标签,下次记得使用正则表达式把不规范的输入转成正确的数组。


分组

除了简单的判断是否匹配之外,正则表达式还有提取字串的强大功能。用()表示的就是要提取的分组(Group)。比如:
^(\d{3})-(\d{3,8})$分别定义了两个组,可以直接从匹配的字符串中提取出区号和号码:
>>> m =re.match(r'^(\d{3})-(\d{3-8})$','010-12345')

>>>m

<_sre.SRE_Match object; span=(0,match='010-12345'>

>>>m.group(0)

'010-12345'

>>>m.group(1)

'010'

>>>m.group(2)

'12345'

如果正则表达式中定义了组,就可以在Match对象上使用group()方法提取出来。

注意到,group(0)是原始字符串,group(1)\group(2)...依次表示第一个、第二个字符串...

提取字符串非常有用,来看一个更凶残的例子:
>>>t ='19:05:30'

>>>m =re.match(r'^(0[0-9]|1[0-9]|2[0-3]|[0-9])\:(0[0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9]|[0-9])\:(0[0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9]|[0-9])$',t)

>>>m.groups()

('19','05','30')

这个正则表达式可以直接识别合法时间但有时候使用正则表达式也无法做到完全验证,如识别日期:

'^(0[1-9]|1[0-2]|[0-9])-(0[1-9]|1[0-9]|2[0-9]|3[0-1]|[0-9])$'

对于日期:'2-30','4-31'这样的非法日期还是识别不了,或者写出来非常困难,这样就需要程序配合识别了。


贪婪匹配

最后需要指出的是正则表达式默认是贪婪匹配,也就是匹配尽可能多的字符。举例如下:

>>>re.match(r'^(\d+)(0*)$','102300').groups()

('102300','')

由于\d+采用贪婪匹配,把后面的0全部匹配掉了,所以0*只能匹配空字符串了。

必须让\d+采用非贪婪匹配,才能把后面的0匹配出来,加个?就可以让\d+采用非贪婪方式匹配:
>>>re.match(r'^(\d+?)(0*)$','12300').groups()

('123','00')


编译

当我们在Python中使用正则表达式时,re模块内部会做两件事:
1、编译正则表达式,如果正则表达式本身不合法,会报错

2、用编译后的正则表达式取匹配字符串

如果一个正则表达式要使用几千次,出于效率考虑,我们可以预编译正则表达式,接下来重复使用就不需要编译这个步骤了,直接匹配:
>>>import re

>>>re_telephone =re.compile(r'^(\d{3})-(\d{3,8})$')

>>>re_telephone.match('010-12345').groups()

('010','12345')

编译后生成Regular Expression对象,由于该对象自己包含了正则表达式,所以调用时不用给出正则字符串。


小结:

正则表达式非常强大,要在一节内讲完是不可能的,如果你经常用到正则表达式,你可能需要一本正则表达式的参考书。

Pyhton 第九章 正则表达式的更多相关文章

  1. Html5 canvas实现粒子时钟的示例代码

    这篇文章主要介绍了Html5 canvas实现粒子时钟的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  2. HTML5数字输入仅接受整数的实现代码

    这篇文章主要介绍了HTML5数字输入仅接受整数的实现代码,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  3. ios – 使用大写符号在字符串swift中获取URL的正则表达式

    我尝试在文本中获取URL.所以,在此之前,我使用了这样一个表达式:但是当用户输入带有大写符号的URL时(例如Http://Google.com,它与它不匹配)我遇到了问题.我试过了:但什么都没发生.解决方法您可以使用正则表达式中的i内联标志关闭区分大小写,有关可用正则表达式功能的详细信息,请参阅FoundationFrameworkReference.(?ismwx-ismwx)Flagsetti

  4. 在Xcode4中,你可以更改用于显示隐形字符的字符吗?

    我更喜欢VisualStudio显示隐形的方式……

  5. XCode 3.2 Ruby和Python模板

    在xcode3.2下,我的ObjectiveCPython/Ruby项目仍然可以打开更新和编译,但是你无法创建新项目.鉴于xcode3.2中缺少ruby和python的所有痕迹(即创建项目并添加新的ruby/python文件),是否有一种简单的方法可以再次安装模板?我发现了一些关于将它们复制到某个文件夹的信息,但我似乎无法让它工作,我怀疑文件夹的位置已经改变为3.2.解决方法3.2中的应用程序模板

  6. ios – NSURLErrorDomain代码-1002下载pdf

    我正在尝试缓存一个网页,然后我可以使用UIWebView显示该网页.我在另一个NSURLSessionDataTask的完成块内的for循环(尝试缓存6个网页)中有相关的NSURLSessionDataTask.当我跑步时,我不断收到此错误:Ayy下载错误,数据:响应:(空)错误:错误域=NSURLErrorDomain代码=-1002“操作无法完成.(NSURLErrorDomain错误-1

  7. ios – 应用程序商店描述特殊字符

    是不是可以在AppStore描述中使用像星星这样的特殊字符了?我得到这个错误:描述不得包含标记语言.说明不得包含以下字符:★提前致谢:)解决方法仍然允许一些unicode字符.以下字符已经过测试并仍然有效:◆√至于现在他们工作正常,但苹果可以随时再次改变条件.

  8. ios – 将数组中的字符转换为整数

    即使我搜索了文档,我似乎无法弄清楚如何做到这一点.我试图弄清楚如何将数组中索引处的字符转换为整数.例如,假设我有一个名为“容器”的字符数组,我无法弄清楚该怎么做:谢谢您的帮助!解决方法Swift并不容易在原始和类型表示之间进行转换.这是一个在此期间应该有所帮助的扩展:这使您可以非常接近您想要的:对于遇到此问题的任何工程师,请参阅rdar://17494834

  9. ios – 如何在Swift 3中使用正则表达式?

    解决方法我相信.当没有其他选项适用时,将使用.allZeros.因此,使用Swift3,您可以传递一个空的选项列表或省略options参数,因为它默认为无选项:要么请注意,在Swift3中,您不再使用error参数.它现在抛出.

  10. ios – lldb断点在类目标c中的所有方法

    如何使用lldb在ObjectiveC类中的所有方法上自动设置断点?

随机推荐

  1. 法国电话号码的正则表达式

    我正在尝试实施一个正则表达式,允许我检查一个号码是否是一个有效的法国电话号码.一定是这样的:要么:这是我实施的但是错了……

  2. 正则表达式 – perl分裂奇怪的行为

    PSperl是5.18.0问题是量词*允许零空间,你必须使用,这意味着1或更多.请注意,F和O之间的空间正好为零.

  3. 正则表达式 – 正则表达式大于和小于

    我想匹配以下任何一个字符:或=或=.这个似乎不起作用:[/]试试这个:它匹配可选地后跟=,或者只是=自身.

  4. 如何使用正则表达式用空格替换字符之间的短划线

    我想用正则表达式替换出现在带空格的字母之间的短划线.例如,用abcd替换ab-cd以下匹配字符–字符序列,但也替换字符[即ab-cd导致d,而不是abcd,因为我希望]我如何适应以上只能取代–部分?

  5. 正则表达式 – /bb | [^ b] {2} /它是如何工作的?

    有人可以解释一下吗?我在t-shirt上看到了这个:它似乎在说:“成为或不成为”怎么样?我好像没找到’e’?

  6. 正则表达式 – 在Scala中验证电子邮件一行

    在我的代码中添加简单的电子邮件验证,我创建了以下函数:这将传递像bob@testmymail.com这样的电子邮件和bobtestmymail.com之类的失败邮件,但是带有空格字符的邮件会漏掉,就像bob@testmymail也会返回true.我可能在这里很傻……当我测试你的正则表达式并且它正在捕捉简单的电子邮件时,我检查了你的代码并看到你正在使用findFirstIn.我相信这是你的问题.findFirstIn将跳转所有空格,直到它匹配字符串中任何位置的某个序列.我相信在你的情况下,最好使用unapp

  7. 正则表达式对小字符串的暴力

    在测试小字符串时,使用正则表达式会带来性能上的好处,还是会强制它们更快?不会通过检查给定字符串的字符是否在指定范围内比使用正则表达式更快来强制它们吗?

  8. 正则表达式 – 为什么`stoutest`不是有效的正则表达式?

    isthedelimiter,thenthematch-only-onceruleof?PATTERN?

  9. 正则表达式 – 替换..与.在R

    我怎样才能替换..我尝试过类似的东西:但它并不像我希望的那样有效.尝试添加fixed=T.

  10. 正则表达式 – 如何在字符串中的特定位置添加字符?

    我正在使用记事本,并希望使用正则表达式替换在字符串中的特定位置插入一个字符.例如,在每行的第6位插入一个逗号是什么意思?如果要在第六个字符后添加字符,请使用搜索和更换从技术上讲,这将用MatchGroup1替换每行的前6个字符,后跟逗号.

返回
顶部