Python正则表达式基础内容附例题

正则表达式

简介

1.定义
即文本的高级匹配模式,提供搜索,替换等功能。其本质是由一系列字符和特殊符号构成的字串,这个字串即正则表达式。
2 原理
通过普通字符和有特定含义的字符,来组成字符串,用以描述一定的字符串规则,比如:重复,位置等,来表达某类特定的字符串,进而匹配。

元字符

普通字符

匹配每一个对应的字符
注: python中正则表达式可以匹配中文

re.findall('ab',"abcdefabcd")
Out: ['ab', 'ab']

或关系 |

· 匹配规则,匹配|两边的正则表达式

In : re.findall('com|cn',"www.baidu.com/www.tmooc.cn")
Out: ['com', 'cn']

匹配字符集 [ 字符集 ]

· 匹配规则: 匹配字符集中的任意一个字符,注意在[ ] 中的元素是或的关系。

e.g.
In : re.findall('[aeiou]',"How are you!")
Out: ['o', 'a', 'e', 'o', 'u']

匹配字符集反集 [ ^字符集 ]

·匹配规则: 除了这个字符集以外的任意一个字符

In : re.findall('[^0-9]',"Use 007 port")
Out: ['U', 's', 'e', ' ', ' ', 'p', 'o', 'r', 't']

匹配字符串的结尾位置 $

· 匹配规则:匹配目标字符串的结尾位置

In : re.findall('Jame$',"Hi,Jame")
Out: ['Jame']

In: re.findall(r"xx$", '38x1x234x35x612x3yxxx')
Out: ['xx']

· 应用:
可以用来判断一个字符串的结尾是不是想要的值。如果不是的话结果就是一个空的列表

匹配字符的重复 * + ? {n}

*

· 匹配规则: 匹配前面的字符出现0次或多次

In : re.findall('wo*',"wooooo~~w!")
Out: ['wooooo', 'w']
+

· 匹配规则: 匹配前面的字符出现1次或多次

In : re.findall('[A-Z][a-z]+',"Hello World")
Out: ['Hello', 'World']

注意: 注意* 和 + 的区别,虽然只是0次和一次为最低下限,但是在实际使用的时候会产生不一样的效果

·匹配规则:匹配前面的字符一个或多次

# 匹配数字,包括正数和负数
In : re.findall('-?[0-9]+',"Jame,age:18, -26")
Out: ['18', '-26']
{n} {m,n}

匹配规则: 匹配前面的字符出现n次,或m-n次

e.g. 匹配手机号码
In : re.findall('1[0-9]{10}',"Jame:13886495728")
Out: ['13886495728']
# 匹配qq号
In : re.findall('[1-9][0-9]{5,10}',"Baron:1259296994") 
Out: ['1259296994']
说明:

单独看着这几个匹配次数的元字符很简单,但是一旦合起来,搭配的方式非常灵活,如和. \w 等元字符搭配可以产生不同的效果

匹配(非)数字字符 \d \D

·匹配规则: \d匹配任意的数字字符,\D 匹配任意非数字字符

In : re.findall('\d{1,5}',"Mysql: 3306, http:80")
Out: ['3306', '80']

匹配任意(非)普通字符 \w \W

· 匹配规则: \w 匹配普通字符,\W 匹配非普通字符
· 说明: 普通字符指数字,字母,下划线,汉字。

匹配任意非空字符 \s \S

· 匹配规则: \s 匹配空字符,\S 匹配非空字符
· 说明:空字符指 空格 \r \n \t \v \f 字符

In : re.findall('\w+\s+\w+',"hello    world")
Out: ['hello    world']

匹配开头结尾位置 \A \Z

·匹配规则: \A 表示开头位置,\Z 表示结尾位置
注: 这个基本用不到

匹配(非)单词的边界位置 \b \B

·匹配规则: \b 表示单词边界 \B表示非单词边界

In : re.findall(r'\bis\b',"This is a test.")
Out: ['is']

总结

这些元字符的熟练运用我认为是正则表达式的基本也是关键,若熟练掌握则此法修成。

类别元字符
匹配字符. […] [^…] \d \D \w \W \s \S
匹配重复* + ? {n} {m,n}
匹配位置^ $ \A \Z \b \B
其他| () \

贪婪模式和非贪婪模式

  1. 定义

贪婪模式: 默认情况下,匹配重复的元字符总是尽可能多的向后匹配内容。比如: * + ? {m,n}

非贪婪模式(懒惰模式): 让匹配重复的元字符尽可能少的向后匹配内容。

  1. 贪婪模式转换为非贪婪模式
  • 在匹配重复元字符后加 ‘?’ 号即可
*  :  *?
+  :  +?
?  :  ??
{m,n} : {m,n}?
e.g.
In : re.findall(r'\(.+?\)',"(abcd)efgh(higk)")
Out: ['(abcd)', '(higk)']

正则表示的分组

  1. 定义
    在正则表达式中,以()建立正则表达式的内部分组,子组是正则表达式的一部分,可以作为内部整体操作对象。
  2. 作用
    · 可以被作为整体的操作,改变元字符的操作对象
e.g.  改变 +号 重复的对象
In : re.search(r'(ab)+',"ababababab").group()
Out: 'ababababab'

e.g. 改变 |号 操作对象
In : re.search(r'(王|李)\w{1,3}',"王小二").group()
Out: '王者荣耀'

· 可以通过编程语言某些接口获取匹配内容中,子组对应的内容部分

# 获取url 协议类型
re.search(r'(https|http|ftp|file)://\S+',"https://www.taobao.com").group(1)
Out:https
  1. 注意事项
    一个正则表达式中可以包含多个子组
    子组可以嵌套,但是不要重叠或者嵌套结构复杂
    子组序列号一般从外到内,从左到右计数

正则表达式匹配原则

  1. 正确性,能够正确的匹配出目标字符串.
  2. 排他性,除了目标字符串之外尽可能少的匹配其他内容.
  3. 全面性,尽可能考虑到目标字符串的所有情况,不遗漏.

Python re模块使用

re.findall(pattern,string,flags = 0)
 功能: 根据正则表达式匹配目标字符串内容
 参数: pattern  正则表达式
      string 目标字符串
      flags  功能标志位,扩展正则表达式的匹配
 返回值: 匹配到的内容列表,如果正则表达式有子组则只能获取到子组对应的内容
re.split(pattern,string,flags = 0)
功能: 使用正则表达式匹配内容,切割目标字符串
参数: pattern  正则表达式
     string 目标字符串
     flags  功能标志位,扩展正则表达式的匹配
返回值: 切割后的内容列表
 re.sub(pattern,replace,string,max,flags = 0)
 功能: 使用一个字符串替换正则表达式匹配到的内容
 参数: pattern  正则表达式
      replace  替换的字符串
      string 目标字符串
      max  最多替换几处,默认替换全部
      flags  功能标志位,扩展正则表达式的匹配
 返回值: 替换后的字符串
 re.subn(pattern,replace,string,max,flags = 0)
 功能: 使用一个字符串替换正则表达式匹配到的内容
 参数: pattern  正则表达式
      replace  替换的字符串
      string 目标字符串
      max  最多替换几处,默认替换全部
      flags  功能标志位,扩展正则表达式的匹配
 返回值: 替换后的字符串和替换了几处
 re.finditer(pattern,string,flags = 0)
 功能: 根据正则表达式匹配目标字符串内容
 参数: pattern  正则表达式
      string 目标字符串
      flags  功能标志位,扩展正则表达式的匹配
 返回值: 匹配结果的迭代器
re.fullmatch(pattern,string,flags=0)
功能:完全匹配某个目标字符串
参数:pattern 正则
	string  目标字符串
返回值:匹配内容match object
re.match(pattern,string,flags=0)
功能:匹配某个目标字符串开始位置
参数:pattern 正则
	string  目标字符串
返回值:匹配内容match object
re.search(pattern,string,flags=0)
功能:匹配目标字符串第一个符合内容
参数:pattern 正则
	string  目标字符串
返回值:匹配内容match object

实例运用

分隔词典

把 s = "apple 苹果"按单词和意思给分开

s = "apple            苹果"
pattern = r"(\w+)"
re.findall(pattern, s)
Out: ['apple', '苹果']

用分组的方式得到对应的组合

计算器(输出计算步骤)

首先我们规定输入的运算式每个字符之间已空格隔开
第一步:我们要提取每个字符,这个可能看起来有点难但是其实就是暴力的 | 操作而已,不要怕
re.findall(’[\d.]+|(|+|-|*|/|)’, eq)
第二步: 如果有括号的话计算括号内的内容,匹配括号内的内容.

pattern = r"\(.+?\)"
list_bracket = re.findall(pattern, eq)

第三步:匹配要计算的乘法和除法

这个就比较简单了,主要是数字之间夹了一个* 或 /

eq = "1+2*3+2*5+3/5"
pattern = r"[0-9]+\*[0-9]+|[0-9]+\/[0-9]+"
re.findall(pattern, eq)

第四部: 匹配要计算的加法和减法
这个和上面基本相同

pattern = r"[0-9]+\+[0-9]+|[0-9]-[0-9]+"
re.findall(pattern, eq)

这里全部的匹配就结束了,每一步的匹配完成之后用eval()计算后,再用re.sub()替换即可

上代码

import re
class CalculateView:
    def __init__(self):
        self.calutating = CalculateControl()

    def view(self):
        print("""
        *******************************************************
                              计算器
        *******************************************************
        说明:输入格式请按在每个字符之间加上空格的格式输入
             输入0退出
        """)

    def main(self):
        while True:
            self.view()
            eq = input("""
        =-请输入-=""")
            if eq == "0":
                print("""
        =- 谢谢使用 -=""")
                break
            # 调整格式
            eq = self.calutating.dispose_input(eq)
            # 去括号
            eq1 = self.calutating.remove_bracket(eq)
            # 算乘除
            eq2 = self.calutating.remove_multiply_divide(eq1)
            self.print_result(eq, eq1, eq2)

    def print_result(self, eq, eq1, eq2):
        """
        打印结果
        """
        print("""
        ---%s"""%eq)
        if eq1 != eq:
            print("""
        ---%s""" % eq1)
        print("""
        ---%s""" % eq2)
        print("""
        ---%s""" % str(eval(eq2)))


#   # 4 + 2 * 3 - 12 / (7 - 5 ) #
class CalculateControl:
    """
    计算器的控制中心
    """

    def remove_bracket(self, eq):
        """
        处理括号内的计算
        :param eq: 需要处理的计算式
        :return: 处理后的计算式
        """
        # 匹配括号内的内容
        pattern = r"(?=\().*?(?<=\))"
        list_bracket = re.findall(pattern, eq)
        for item in list_bracket:
            # 用计算好的结果替换括号内的内容
            eq = re.sub(pattern, str(eval(item)), eq, 1)
        return eq

    def remove_multiply_divide(self, eq):
        """
        去除乘除的计算
        :param eq: 需要处理的计算式
        :return: 处理好的计算式
        """
        # 匹配乘号运算的对象和除号运算的对象
        pattern = r"\d+\*\d+|\d+/\d+"
        format_list = re.findall(pattern, eq)
        for item in format_list:
            # 用乘除后的结果替换原来的 ×*×  ×/×
            eq = re.sub(pattern, str(eval(item)), eq, 1)
        return eq

    def dispose_input(self, eq):
        """
        处理输入的计算式
        :param eq: 未处理的计算式
        :return: 处理过的计算式,去除空格和#
        """
        # 匹配输入的内容,去除#
        format_list = re.findall('[\d\.]+|\(|\+|\-|\*|\/|\)', eq)
        # 用生成器表达式和"".join()函数 去除原式中的空格
        eq = "".join((item for item in format_list))
        return eq


if __name__ == "__main__":
    ca = CalculateView()
    ca.main()

### 编译原理中正则表达式的示例题目及其解析 #### 题目一:设计一个正则表达式,接受仅由字符 `a` 和 `b` 组成的字符串,并且该字符串至少包含两个连续的 `a`。 解答如下: 可以通过定义正则表达式 `(ab*|b)*aa(b|ba*)*` 来解决这个问题。这里解释一下各个部分的作用: - `(ab*|b)` 表达的是任意数量的 `b` 后面跟着一个 `a` 或者单独的一个 `b`[^1]。 - `aa` 是核心条件,表示必须存在至少两个连续的 `a`[^2]。 - `(b|ba*)*` 则允许后续有任意多个 `b` 或者以 `b` 开头并跟随零个或多个 `a` 的组合[^3]。 最终的结果是一个能够识别满足上述特性的字符串的正则表达式。 --- #### 题目二:编写一个正则表达式,用于匹配所有长度为偶数的二进制字符串。 解决方案可以是这样的正则表达式:`(00|11|01|10)*` 具体说明如下: - 这里的基本单元是由两位组成的二进制对 (即 `00`, `11`, `01`, `10`),它们各自代表了一个有效的、具有固定长度的片段[^4]。 - 使用星号 (`*`) 将这些基本单元重复多次,从而形成任何可能的偶数长度的合法字符串序列[^5]。 因此,只要输入符合这种模式,则必然属于我们所期望的一类字符串——那些拥有偶数位数的纯二进制形式的数据项。 ```python import re pattern = r"(00|11|01|10)*" test_strings = ["0", "1", "00", "11", "01", "10", "000", "111"] for s in test_strings: match_result = bool(re.fullmatch(pattern, s)) print(f"'{s}' matches? {match_result}") ``` 以上脚本展示了如何运用 Python 中的 `re` 模块去检测给定测试集中哪些成员能成功配对此特定规则下的正则表达式[^6]。 --- #### 题目三:构建一个正则表达式,它应该只接收形如 `{n}m{n}` 形式的字符串,其中 n ≥ 1 而 m 可以为任意大于等于零次出现次数的字母表中的某个单一字符 c (c ∈ Σ)。 对于此类问题,我们可以采用下面所示的方法来创建相应的正则表达式结构: 假设我们的字母表Σ={a,b},那么对应的正则表达式将是:`(a+b)(a*b*a+a*b*b)*(a+b)`. 进一步分解来看, - 外层括号内的第一个(a+b),意味着开头处必然是单个'a'或者'b'. - 接下来的中间部分(a*b*a+a*b*b)* ,涵盖了各种情况下的'm',它可以为空也可以是非空的各种情形. - 最后的外侧另一个(a+b),再次强调结尾也需对应相同类型的起始符号. 这便构成了完整的针对指定格式字符串的有效判定机制[^7]. ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值