详解正则表达式(re) 一

详解正则表达式(re) 一

research 查找文本中的模式compile 编译findall 查询所有匹配重复与贪婪

re

正则表达式 可以用形式化的语法描述文本匹配模式,模式又被正则表达式引擎编译成指令;执行指令并提供一个字符串作为输入,就可以知道给定的输入有没有与模式相匹配。 文字比较空洞还是直接看例子吧。


search 查找文本中的模式

查找一段文本中有没有出现 sql 这个字符串。

In [1]: s ="I like sql"                                                         

In [2]: ‘sql‘ in s
Out[2]: True

可以看到根本没有用到 re 这个库就把问题给解决了;但是没有 bug 吗?

In [3]: s = "I like www.sqlpy.com"                                              

In [4]: ‘sql‘ in s
Out[4]: True
# 这样的太不应该了,我想要的只是 sql 而不是 xxxsqlxx。

用 re 就没有 bug 了。

In [1]: import re                                                               

In [2]: p = r"\bsql\b"                                                          

In [3]: s = "I like sql"                                                        

In [4]: re.search(p,s)
Out[4]: <re.Match object; span=(7, 10), match=‘sql‘>

In [5]: s = "I like www.sqlpy.com"                                              

In [6]: re.search(p,s)           # 可以看到不在有匹配                                               

In [7]:

原因在于用 re 我们把可以把自己要找到内容描述的更加清楚,‘sql‘ in s 讲的是 s 中是否包含sql 这三个字符,而 r"\bsql\b" 描述的是 ‘sql‘ 这个单词。


compile 编译

上面的代码还有一个问题,re.search(p,s) 运行到这里的时候就会对模式进行编译,运行几次就编译几次,对于反复用到的模式提前编译是一个好的选择。下面是两种处理方式的性能比较。

#!/usr/bin/evn python3

import re
import time

# 提前把用到的模式编译好
global_pattern = re.compile(r"\bsql\b")

def fun_a():
    """在每次用的时候都编译模式
    """
    p = r"\bsql\b"
    s = "I like sql"
    return re.search(p, s)

def fun_b():
    """使用提交编译好的模式
    """
    global global_pattern
    s = "I like sql"
    return global_pattern.search(s)

def run(fun, times=1000):
    start_at = time.time()
    for t in range(times):
        fun()

    complete_at = time.time()
    print(
        f"function {fun.__name__} execute {times} times cost {complete_at - start_at}")

if __name__ == "__main__":
    run(fun_a, 10000)
    run(fun_b, 10000)

运行结果。

python3 main.py
function fun_a execute 10000 times cost 0.013822078704833984
function fun_b execute 10000 times cost 0.006231784820556641

可以看到提前编译要比即时编译快 100% 。


findall 查询所有匹配

通过 search 只能知道有没有匹配,如果有多处匹配我们怎么提取出来呢?

In [1]: import re                                                               

In [2]: s = "ab abb abbb abbbb"                                                 

In [3]: p = r"ab*"                                                              

In [4]: re.search(p,s)
Out[4]: <re.Match object; span=(0, 2), match=‘ab‘>

In [5]: for m in re.findall(p,s):
   ...:     print(m)
   ...:
ab
abb
abbb
abbbb

In [6]: type(re.findall(p,s))
Out[6]: list

可以看到 findall 返回的是一列表而列表的元素是字符串,如果有大量的结果被匹配到,比如几千几亿个,这个 list 是非常吃内存的,理节约内存的方式是使用生成器。

In [7]: for m in re.finditer(p,s):
   ...:     print(m)
   ...:
<re.Match object; span=(0, 2), match=‘ab‘>
<re.Match object; span=(3, 6), match=‘abb‘>
<re.Match object; span=(7, 11), match=‘abbb‘>
<re.Match object; span=(12, 17), match=‘abbbb‘>

In [8]: type(re.finditer(p,s))
Out[8]: callable_iterator


重复与贪婪

正则表达式对重复的描述包含 5 种形式。

1、ab* 说的是 ‘a‘ 后面的 ‘b‘ 可以是零个也可以是任意多个。 2、ab+ 说的是 ‘a‘ 后面的 ‘b‘ 至少是一个。 3、ab? 说的是 ‘a‘ 后面的 ‘b‘ 要么没有要么只有一个。4、ab{5}说的是 ‘a‘ 后面的 ‘b‘ 一定要是 5 个,当然这里的 5 也可以改在其它的数值,视需求而定。 5、ab{5,8} 说的是可以是 5 个到 8 个之间([5,8]开边都是闭区间)。

默认情况下正则表达式工作在贪婪模式,也就是说它会倾向于匹配出更多的字符串,看一下面的例子。

In [1]: import re                                                               

In [2]: s = "abbbb"                                                             

In [3]: p = "ab*"                                                               

In [4]: re.search(p,s)
Out[4]: <re.Match object; span=(0, 5), match=‘abbbb‘>

怎么让它匹配出尽可能少的字符串呢?答案是在正则表达式的结尾处加上一个?号,看下面的代码。

In [5]: p = "ab*?"                                                              

In [6]: re.search(p,s)
Out[6]: <re.Match object; span=(0, 1), match=‘a‘>

原文地址:https://www.cnblogs.com/JiangLe/p/12687155.html

时间: 2024-11-13 06:35:50

详解正则表达式(re) 一的相关文章

详解正则表达式以及文本处理工具&mdash;grep、egrep的用法和特性

一.grep (1)grep简介 grep:全称是Global search REgular expression and Print out the line,全局搜索正则表达式并输出合适的行. grep是一种强大的文本搜索工具,根据用户指定的文本模式(搜索条件)对目标文件进行逐行搜索,显示能匹配到的行.(只对文本进行搜索处理) Unix的grep家族包含grep.egrep和fgrep. (2)grep的用法 语法格式:grep [option]... 'PATTERN' FILE... 选

Sed 命令详解 正则表达式元字符

1.简介 sed是非交互式的编辑器.它不会修改文件,除非使用shell重定向来保存结果.默认情况下,所有的输出行都被打印到屏幕上. sed编辑器逐行处理文件(或输入),并将结果发送到屏幕.具体过程如下:首先sed把当前正在处理的行保存在一个临时缓存区中(也称为模式空间),然后处理临时缓冲区中的行,完成后把该行发送到屏幕上.sed每处理完一行就将其从临时缓冲区删除,然后将下一行读入,进行处理和显示.处理完输入文件的最后一行后,sed便结束运行.sed把每一行都存在临时缓冲区中,对这个副本进行编辑,

JavaScript系列文章:详解正则表达式之二

在上一篇文章中我们讲了正则表达式的基本用法,接下来博主想聊聊其中的细节,今天就从正则修饰符开始吧. 正则修饰符又称为正则标记(flags),它会对正则的匹配规则做限定,进而影响匹配的最终结果.在上次的文章中我们也提到过,正则修饰符一共有以下几种,可以单独使用,也可以组合使用: /\w+/g; // global search /\w+/i; // ignore case /\w+/m; // multi-line /\w+/u; // unicode /\w+/y; // sticky /\w+

iOS开发之详解正则表达式

本文由Charles翻自raywenderlich原文:NSRegularExpression Tutorial: Getting Started更新提示:本教程被James Frost更新到了iOS8和swift.Tutorial团队成员的Soheil Azarpour完成最初发布.正则表达式(广为所知的"regex")是一个字符串或一个字符序列来说明一种模式,把它作为一个搜索字符串-非常强大! 在一个文本编辑器或文字处理器中普通的旧式搜索只允许你进行简单的匹配.正则表达式可以实现这

JavaScript系列文章:详解正则表达式之一

正则表达式是一个精巧的利器,经常用来在字符串中查找和替换,JavaScript语言参照Perl,也提供了正则表达式相关模块,开发当中非常实用,在一些类库或是框架中,比如jQuery,就存在大量的正则表达式,所以说学好正则表达式,是提高开发技能的一项基本要求.那么今天博主就来详细总结一下正则表达式的相关知识,希望不熟悉的同学们,也能够掌握正则表达式的原理及应用. 在JS中,创建正则表达式有两种方式,一种是字面量方式,一种是构造器方式,如下所示: var regex = /\w+/; // 或者 v

详解JavaScript中的replace()函数

Javascript中字符串对象有一个方法replace(),它的作用非常强大.这里把它的用法整理一下.  一.方法简介 该方法的签名是:replace([RegExp|String],[String|Function]). 该方法 返回一个新的字符串,但并不改变字符串本身. 该方法接收2个参数,第一个参数可以是字符串,也可以是一个正则表达式:第二个参数可以是一个字符串,也可以是一个函数.其中第2个参数如果是函数,那么用起来是十分强大而且灵活的,不过相对来说也比较难掌握.下面就其用法进行详细说明

JAVA正则表达式:Pattern类与Matcher类详解(转)

java.util.regex是一个用正则表达式所订制的模式来对字符串进行匹配工作的类库包.它包括两个类:Pattern和Matcher Pattern 一个Pattern是一个正则表达式经编译后的表现模式. Matcher 一个Matcher对象是一个状态机器,它依据Pattern对象做为匹配模式对字符串展开匹配检查. 首先一个Pattern实例订制了一个所用语法与PERL的类似的正则表达式经编译后的模式,然后一个Matcher实例在这个给定的Pattern实例的模式控制下进行字符串的匹配工作

详解 Python3 正则表达式系列索引

详解 Python3 正则表达式(一) 详解 Python3 正则表达式(二) 详解 Python3 正则表达式(三) 详解 Python3 正则表达式(四) 详解 Python3 正则表达式(五) 详解 Python3 正则表达式(六) 详解 Python3 正则表达式(七)

详解 Python3 正则表达式(二)

上一篇:详解 Python3 正则表达式(一) 本文翻译自:https://docs.python.org/3.4/howto/regex.html 博主对此做了一些批注和修改 ^_^ 使用正则表达式 现在我们开始来写一些简单的正则表达式吧.Python 通过 re 模块为正则表达式引擎提供一个接口,同时允许你将正则表达式编译成模式对象,并用它们来进行匹配. 批注:re 模块是使用 C 语言编写,所以效率比你用普通的字符串方法要高得多:将正则表达式进行编译(compile)也是为了进一步提高效率