Regex 正则表达式入门

Stella981
• 阅读 485

Regex 正则表达式入门


0,什么是正则表达式

正则表达式Regular Expression简写为Regex),又称为规则表达式,它是一种强大的文本匹配模式,其用于在字符串中查找匹配符合特定规则的子串。

正则表达式是独立于编程语言而存在的,它并不依赖于某种编程语言。只要一种编程语言实现了正则表达式引擎,那么这种编程语言,就具备了正则表达式模式匹配的功能。每种工具编程语言对正则表达式的实现,虽有细节上的不同,但基本的使用是相同的。

正则表达式的基本工作原理如下:

Regex 正则表达式入门

1,正则表达式的由来

1956 年,美国数学家Stephen Kleene 在两位神经生理学家(Warren McCullochWalter Pitts)的早期工作的基础上,发表了一篇标题为神经网事件的表示法的论文,由此引入了正则表达式的概念。

之后,Unix 之父Ken Thompson把这一成果应用于计算搜索算法的一些早期研究。随后,他将这一符号系统应用于Unix 系统中的 qed 编辑器,这是正则表达式的第一个实用程序。

此后,正则表达式被广泛的应用于类Unix 系统的工具中,如 grepperl 等。

2,正则表达式工具

RegexBuddy 是一个很不错的软件。

Regexr 是一个在线工具。

3,正则表达式语法

正则表达式由一些普通字符(比如英文字母,数字)和元字符(代表特定含义)组成。

正则表达式作为一个字符模板,在字符串中匹配一个或多个符合特定规则的子串。

3.1,元字符

元字符就是包含特定含义的字符。如果想匹配这些元字符,需要使用转义字符\ 进行转义。

下表是一些常用的元字符:

字符

含义

\

转义字符,常用于转义元字符

.

匹配除换行符\n 之外的任何单字符

$

匹配字符串的结尾位置

^

匹配字符串的开始位置。当写在中括号[]内时,表示不匹配该中括号中的字符集合

[^xy]

匹配非x非y字符

()

被小括号包含的多个字符,将作为一整个字符

(pattern)

写在小括号()内的表达式,表示一个分组,用于提取内容

(?:pattern)

只表示一个分组,不提取内容

[]

被中括号包含的多个字符,这多个字符的关系是逻辑或的关系

[xyz]

字符集合,匹配xyz

[0-9]

匹配09之间的数字

[a-z]

匹配az之间的字符

[^a-z]

匹配不在az范围内的任意字符

`

`

`x

y`

\b

匹配一个单词边界

\B

匹配非单词边界

\d

匹配一个数字字符,等价于[0-9]

\D

匹配一个非数字字符,等价于[^0-9]

\s

匹配任何空白字符,包括空格制表符

\S

匹配任何非空白字符

\w

匹配字母数字下划线,等价于[A-Za-z0-9_]

\W

匹配非字母非数字非下划线,等价于[^A-Za-z0-9_]

\f

匹配换页符

\n

匹配换行符

\r

匹配回车符

\t

匹配制表符

\v

匹配垂直制表符

3.2,限定符

限定符也属于元字符,用来限定一个子表达式出现的次数。

字符

含义

*

匹配前面的子表达式零次多次

+

匹配前面的子表达式一次多次

?

匹配前面的子表达式零次一次

{n}

匹配前面的子表达式n次

{n,}

匹配前面的子表达式至少n次

{n,m}

匹配前面的子表达式n 到m 次

4,正则表达式示例

我们逐个介绍一下每种元字符的使用方式,下面的例子我们都使用RegexBuddy 软件来演示。

4.1,转义字符\

转义字符用来对一些元字符进行转义,使这些元字符失去其特定的含义,只表示一个普通的字符。

比如我们想匹配字符串aaa^bbb 中的a^b 子串,我们需要用模式a\^b 来匹配,^ 之前需要加一个转义字符\


Regex 正则表达式入门


4.2,元字符.

元字符. 可匹配任意(除了换行符\n)的单字符,意思就是. 可以代表任意(除了换行符\n)的单字符。


Regex 正则表达式入门


4.3,开始位置^与结束位置$

符号^ 表示匹配的子串在行首,符号$ 表示匹配的子串在行尾


匹配行首

Regex 正则表达式入门


匹配行尾

Regex 正则表达式入门


行首行尾

Regex 正则表达式入门

4.4,逻辑或|

符号| 写在两个子表达式之间表示逻辑或的意思。

例如模式串ab|cd,匹配abcd


Regex 正则表达式入门


4.5,限定符

限定符用于限定一个子表达式出现的次数,一共6 种,这里给出一些示例。

符号*

模式串ab*c,表示字符ac 之间需要出现0 次多次字符b


Regex 正则表达式入门


符号+

模式串ab+c,表示字符ac 之间需要出现1 次多次字符b,即至少出现1次字符b


Regex 正则表达式入门


符号?

模式串ab?c,表示字符ac 之间需要出现0 次1次字符b


Regex 正则表达式入门


符号{n}{n,}{n,m}

  • ab{3}c:符号b 出现的次数必须是3
  • ab{3,}c:符号b 出现的次数必须大于等于3
  • ab{3,5}c:符号b 出现的次数必须在35 之间,包括35

Regex 正则表达式入门


4.6,字符簇[]

写在中括号[] 内的多个字符代表逻辑或的意思。

模式串a[bef]c,表示ac中间的字符必须是bef


Regex 正则表达式入门


当符号^ 写在中括号[] 内时,表示逻辑非的意思。

模式串a[^bef]c,表示ac中间的字符不能是bef


Regex 正则表达式入门


符号- 写在中括号[],表示范围的意思:

示例

含义

[a-z]

表示az 之间的任意字符

[A-Z]

表示AZ 之间的任意字符

[0-9]

表示09 之间的任意数字,含义同\d

[^0-9]

表示任意非数字,含义同\D

[A-Za-z0-9_]

表示任意字母数字下划线 ,含义同\w

[^A-Za-z0-9_]

表示任意非字母非数字非下划线 ,含义同\W

[ \f\r\t\n]

表示任意的空白字符,含义同\s

[^ \f\r\t\n]

表示任意的非空白字符,含义同\S

4.7,字符组合()

写在小括号()中的多个字符,会被看成一个整体。


Regex 正则表达式入门


4.8,单词边界\b\B

符号\b 是指一个单词边界,比如空白字符和标点符号等。 符号\B 表示非单词边界


Regex 正则表达式入门


5,贪婪与非贪婪模式

正则表达式中贪婪的意思就是贪多,意思就是正则在匹配的过程中,总是去匹配尽可能多的字符,符号? 可以将贪婪转换为非贪婪


Regex 正则表达式入门


6,在Python 中使用正则

Python 中提供了re 模块,用于支持正则表达式功能。

python 中一般在表达式前加r,表示原始字符,不用考虑转义的问题。例如r'abc'

下面打开python 终端:

  • 首先引入模块,import re

  • help(re) 可查看re 模块帮助手册

  • dir(re) 可查看其支持的属性和方法

    python 打开python 终端


    Python 2.7.17 (default, Nov 7 2019, 10:07:09) [GCC 7.4.0] on linux2 Type "help", "copyright", "credits" or "license" for more information.

    import re # 引入re 模块

    help(re) # 查看帮助手册

    dir(re) # 查看re 支持的属性和方法

6.1,re 模块常用方法

方法

含义

match

用于匹配表达式

search

查找匹配项

findall

查找所有的匹配项

compile

编译正则表达式

详细解释:

match(pattern, string, flags=0)
        Try to apply the pattern at the start of the string, returning
        a match object, or None if no match was found.

search(pattern, string, flags=0)
        Scan through string looking for a match to the pattern, returning
        a match object, or None if no match was found.
        
findall(pattern, string, flags=0)
        Return a list of all non-overlapping matches in the string.
        
        If one or more groups are present in the pattern, return a
        list of groups; this will be a list of tuples if the pattern
        has more than one group.
        
        Empty matches are included in the result.

compile(pattern, flags=0)
        Compile a regular expression pattern, returning a pattern object.

可以看到,每个方法中都有一个flag 参数,它表示匹配模式,默认值为0,表示普通模式。

flag 参数的值有以下几种选择,可以使用符号| 连接多种选择:

`I/IGNORECASE`  Perform case-insensitive matching.
`L/LOCALE`      Make \w, \W, \b, \B, dependent on the current locale.
`M/MULTILINE`   "^" matches the beginning of lines (after a newline)
                as well as the string.
                "$" matches the end of lines (before a newline) as well
                as the end of the string.
`S/DOTALL`      "." matches any character at all, including the newline.
`X/VERBOSE`     Ignore whitespace and comments for nicer looking RE's.
`U/UNICODE`     Make \w, \W, \b, \B, dependent on the Unicode locale.

6.2,match 方法

re.match 尝试从字符串的起始位置开始匹配:

  • 成功:返回SRE_Match 对象

  • 失败:返回None

    m = re.match(r'abc', 'abcde') print m # 匹配成功 <_sre.SRE_Match object at 0x7f91544cff80>

    m = re.match(r'abc', 'fabcde') print m # fabcde 不是以abc 开头,匹配失败
    None

6.3,search 方法

re.search 扫描整个字符串,直到找到第一个成功的匹配:

  • 成功:返回SRE_Match 对象

  • 失败:返回None

    m = re.search(r'abc', 'abcde') print m # 匹配成功 <_sre.SRE_Match object at 0x7f91544cff80>

    m = re.search(r'abc', 'fabcde') print m # 匹配成功 <_sre.SRE_Match object at 0x7f9154521b90>

6.4,findall 方法

re.findall 在字符串中查找所有匹配的子串:

  • 成功:返回一个列表

  • 失败:返回空列表[]

    re.findall(r'abc', 'fabcdeabc') ['abc', 'abc'] # 找到两个abc 子串

    re.findall(r'abce', 'fabcdeabc') [] # 没找到子串

6.5,compile 方法

在使用正则时,re 模块会先将正则表达式进行编译,然后才会去字符串中匹配。

如果一个正则表达式会使用很多次,我们可以使用re.compile 方法对表达式进行预编译,这样就不会在每次用到这个表达式时都进行编译,有助于提高效率。

该方法返回一个SRE_Pattern 对象,该对象又包含matchsearchfindall 等方法,使用方法如下:

>>> reg =  re.compile(r'abc')      # 编译
>>> 
>>> type(reg)
<type '_sre.SRE_Pattern'>
>>>
>>> reg.findall('fabcdeabc')      # 找到两个
['abc', 'abc']  
>>> 
>>> reg.match('fabcdeabc')        # 没有匹配上
>>> 
>>> reg.search('fabcdeabc')       # 匹配上
<_sre.SRE_Match object at 0x7f9154521b90>

6.6,SRE_Match 对象

SRE_Match 对象用于获取分组,写在小括号()内的表达式是一个分组。

>>> # 正则中包含两个分组
>>> m = re.match(r'(\d*)-(\w*)', '123-abc-')
>>> m
<_sre.SRE_Match object at 0x7f91544e0ae0>
>>> m.group(0) # 获取整个匹配的串,同 m.group()
'123-abc'
>>> m.group(1) # 获取第一个分组
'123'
>>> m.group(2) # 获取第二个分组
'abc'
>>>

6.7,match,search,findall 比较

我们来看下matchsearchfindall 三个方法的异同点:

  • match:必须从字符串的开头匹配,只会有一个匹配项,返回结果是SRE_Match 对象
  • search:扫描整个字符串,直到匹配到第一个为止,只会有一个匹配项,返回结果是SRE_Match 对象
  • findall:扫描整个字符串,返回所有的匹配项,返回结果是一个字符串列表

(完。)


欢迎关注作者公众号,获取更多技术干货。

Regex 正则表达式入门

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Stella981 Stella981
3年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
11个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这