史上最详细的正则表达式教程

史上最详细的正则表达式教程正则表达式正则表达式的作用:在实际开发过程中经常会有查找符合某些复杂规则的字符串的需要,比如:邮箱、图片地址、手机号码等,这时候想匹配或者查找符合某些规则的字符串就可以使用正则表达式了。正则表达式概念正则表达式就是记录文本规则的代码正则表达式的特点正则表达式的语法很令人头疼,可读性差正则表达式通用行很强,能够适用于很多编程语言re…

大家好,欢迎来到IT知识分享网。史上最详细的正则表达式教程"

正则表达式


正则表达式的作用:

在实际开发过程中经常会有查找符合某些复杂规则的字符串的需要,比如:邮箱、图片地址、手机号码等,这时候想匹配或者查找符合某些规则的字符串就可以使用正则表达式了。

正则表达式概念

正则表达式就是记录文本规则的代码

正则表达式的特点
正则表达式的语法很令人头疼,可读性差
正则表达式通用行很强,能够适用于很多编程语言
re模块的使用过程

Python中需要通过正则表达式对字符串进行匹配的时候,可以使用一个模块,名字为re

    # 导入re模块
    import re

    # 使用match方法进行匹配操作
    result = re.match(正则表达式,要匹配的字符串)

    # 如果上一步匹配到数据的话,可以使用group方法来提取数据
    result.group()

注意:re.match() 根据正则表达式从头开始匹配字符串数据

开始进入正题

匹配单个字符

代码 功能
. 匹配任意1个字符(除了\n)
[ ] 匹配[ ]中列举的字符
\d 匹配数字,即0-9
\D 匹配非数字,即不是数字
\s 匹配空白,即 空格,tab键
\S 匹配非空白
\w 匹配非特殊字符,即a-z、A-Z、0-9、_、汉字
\W 匹配特殊字符,即非字母、非数字、非汉字
# . 匹配任意1个字符(除了\n)
# [ ]   匹配[ ]中列举的字符[ab456c][a-z]
# \d    匹配数字,即0-9
# \D    匹配非数字,即不是数字
# \s    匹配空白,即 空格,tab键\t,\n
# \S    匹配非空白
# \w    匹配单词字符,即a-z、A-Z、0-9、_,国家的文字
# \W    匹配非单词字符

# 匹配任意一个数字
# 使用\d
# 判断用户是否输入的是速度与激情系列
import re

# print(re.match("速度与激情\d", "速度与激情2").group())
# print(re.match("速度与激情\d", "速度与激情0").group())
# print(re.match("速度与激情\d", "速度与激情9").group())
# print(re.match("速度与激情\d", "速度与激情a").group())




# 使用[]
# 格式1:[单个值,...]
# 判断用户只想看1,4,8的速度与激情

# print(re.match("速度与激情[148]", "速度与激情1").group())
# print(re.match("速度与激情[148]", "速度与激情4").group())
# print(re.match("速度与激情[148]", "速度与激情8").group())
# print(re.match("速度与激情[148]", "速度与激情9").group())



# 格式2:[范围,...]
# 判断用户只看18的速度与激情
# print(re.match("速度与激情[12345678]", "速度与激情1").group())
# print(re.match("速度与激情[12345678]", "速度与激情8").group())
# print(re.match("速度与激情[1-8]", "速度与激情2").group())
# print(re.match("速度与激情[1-8]", "速度与激情8").group())
# # print(re.match("速度与激情[1-8]", "速度与激情9").group())




# 格式3:[数字字符]
# 判断用户输入的速度与激情18或者速度与激情a-h
#
# print(re.match("速度与激情[1-8]", "速度与激情8").group())
# print(re.match("速度与激情[a-h]", "速度与激情a").group())
# print(re.match("速度与激情[a-h]", "速度与激情h").group())
# print(re.match("速度与激情[a-h]", "速度与激情e").group())
# print(re.match("速度与激情[1-8a-h]", "速度与激情a").group())
# print(re.match("速度与激情[1-8a-h]", "速度与激情8").group())



# 使用\w 即a-z、A-Z、0-9、_这个范围太广,不要轻易用,汉字也可以匹配,其他的国家的语言也可以匹配
# 匹配的单词字符
# 判断用户输入包含速度与激情
# print(re.match("速度与激情\w", "速度与激情8").group())
# print(re.match("速度与激情\w", "速度与激情a").group())
# print(re.match("速度与激情\w", "速度与激情z").group())
# print(re.match("速度与激情\w", "速度与激情A").group())
# print(re.match("速度与激情\w", "速度与激情Z").group())
# print(re.match("速度与激情\w", "速度与激情_").group())
# print(re.match("速度与激情\w", "速度与激情好").group())
# print(re.match("速度与激情\w", "速度与激情あなたのことが好きです").group())
#


# 使用\s
# --匹配空白字符
# --空格 或者 tab(\t),\n换行
# --判断用户速度与激情 8
# print(re.match("速度与激情\s8", "速度与激情 8").group())
# print(re.match("速度与激情\s8", "速度与激情\t8").group())
# print(re.match("速度与激情\s8", "速度与激情\n8").group())
#

# --大写是所有小写的非*******

# .匹配任意1个字符(除了\n)
#   --匹配任意的字符
#   --判断包含速度与激情字符串的
# print(re.match("速度与激情.", "速度与激情\tadf").group())
# print(re.match("速度与激情.", "速度与激情\nadf").group())
匹配多个字符的相关格式
代码 功能
* 匹配前一个字符出现0次或者无限次,即可有可无
+ 匹配前一个字符出现1次或者无限次,即至少有1次
? 匹配前一个字符出现1次或者0次,即要么有1次,要么没有
{m} 匹配前一个字符出现m次
{m,n} 匹配前一个字符出现从m到n次
# -- 匹配的规则
# 字符 功能
# * 匹配前一个字符出现0次或者无限次,即可有可无
# + 匹配前一个字符出现1次或者无限次,即至少有1次
# ? 匹配前一个字符出现1次或者0次,即要么有1次,要么没有
# {m} 匹配前一个字符出现m次 \d{3}
# {m,n} 匹配前一个字符出现从m到n次 \d{4,6}

# 使用 类型{}
# 用来表示一个字符出现多少次
# 匹配速度与激情1,速度与激情12
import re

# print(re.match("速度与激情\d", "速度与激情1").group())
# print(re.match("速度与激情\d\d", "速度与激情12").group())
# print(re.match("速度与激情\d{1,2}", "速度与激情12").group())
# print(re.match("速度与激情\d{1,2}", "速度与激情1").group())


# 匹配手机号11位

# print(re.match("\d{11}", "12345678901").group())

# 判断电话号码是否021 - 开头的后面8位电话号码
# 例: 021 - 12345678
# 判断电话号

# print(re.match("021-\d{8}", "021-12345678").group())


# 使用?
# 用来表示有一个字符或者没有字符
# 用户输入的电话号码有时有'-'有时没有
# 例:02112345678 或者 021-12345678

# print(re.match("021\d{8}", "02112345678").group())
# print(re.match("021-\d{8}", "021-12345678").group())
# print(re.match("021-?\d{8}", "021-12345678").group())
# print(re.match("021-?\d{8}", "02112345678").group())
#
#



# 有些地方是三位电话号码开头,有些是四位电话号码开头
# 0571-8123456
# 021-12345678

# print(re.match("\d{3,4}-?\d{7,8}", "0571-8123456").group())
# print(re.match("\d{3,4}-?\d{7,8}", "021-12345678").group())

# *
# 表示0或者无限次
# 匹配一段文字或者没有输入文字

str = """今天天气不错 我们可以出去运动一下! """

# print(re.match(".*", str).group())
print(re.match(".*", str, re.S).group())  # re.S这个就是跟.*配合在一起让我们的真正的所有的都能匹配

# +
# 表示至少一次,不能为空
print(re.match(".*", "").group())
print(re.match(".+", " ").group())
匹配开头和结尾的正则表达式
代码 功能
^ 匹配字符串开头
$ 匹配字符串结尾
[^指定字符] 表示除了指定字符都匹配
# [^字符]这个是固定的一个语法,这个意思就是非
# 场景hello@163.com hello@163.com,我们想取到第一个邮箱
# 如果写字符串有可能会有错,他会去匹配一个字符串出错
import re

str = "hello@163.com hello@163.com"
print(re.match(".{4,20}@163\.com", str).group())

print(re.match("[^@]+@163\.com", str).group())

# [^字符]字符 非字符

print(re.match("[^bc]", "bc"))
匹配分组相关正则表达式
代码 功能
| 匹配左右任意一个表达式
(ab) 将括号中字符作为一个分组
\num 引用分组num匹配到的字符串
(?P) 分组起别名
(?P=name) 引用别名为name分组匹配到的字符串
# | 相当于python中的or
# 案例:匹配出163或者126的邮箱
import re

str = "hello@163.com"

# print(re.match(".{4,20}@(163|126)\.com", str).group())

# ()还可以单独取出匹配的某一部分数据
# 案例:取出邮箱的类型(只要163,126),后期可以编计用户那个邮箱用的多

# print(re.match(".{4,20}@(163|126)\.com", str).group(0))
# print(re.match("(.{4,20})@(163|126)\.com", str).group(1))
# print(re.match("(.{4,20})@(163|126)\.com", str).group(2))
# print(re.match("(.{4,20})@((163|126)\.com)", str).group(2))



# \num用来取第几组用()包裹的数据 \1取第一个内部的括号位置的值
# 格式(xxx)\1 :\1表示获取(xxx)的值
# 案例<html>hh</html> # 这个一定是有字母,开始跟结束的字母必须一样

# str_data = "<html>hh</html> "
# print(re.match("<([a-zA-Z]+)>.*</\\1>", str_data).group())



# 案例<html><body>hh</body></html>
str_data = "<html><body>hh</body></html>"
# print(re.match("<([a-zA-Z]+)><([a-zA-Z]+)>.*</\\2></\\1>", str_data).group())


# 使用别名给分组取别名,了解一下
# 格式:(?P<别名>xxx)(?P=别名)
# 案例<html><body>hh</body></html>
# 提示问题没错
print(re.match("<(?P<name1>[a-zA-Z]+)><(?P<name2>[a-zA-Z]+)>.*</(?P=name2)></(?P=name1)>", str_data).group())

注意:(分组数据):分组数是从左到右的方式进行分配的

正则的高级用法
代码 功能
search 不会从头开始匹配,只要匹配到数据就结束
findall 查询结果集
sub 将匹配到的数据进行替换
split 根据匹配进行切割字符串,并返回一个列表
# 查询结果
# search 不会从头开始匹配,只要匹配到数据就结束
# 案例:匹配出文章阅读的次数中的次数
# 数据:"阅读次数为 9999"

import re

# print(re.search("\d+", "阅读次数为 9999").group())



# 查询结果集
# findall
# 案例: 统计出python、c、c + +相应文章阅读的次数
# 数据: "python = 9999, c = 7890, c++ = 12345"

# print(re.findall("\d+", "python = 9999, c = 7890, c++ = 12345"))



# 字符串切割
# split
# 切割字符串“info:xiaoZhang 33 shandong”, 根据:或者空格
# print(re.split(":|\s", "info:xiaoZhang 33 shandong"))


# 替换数据
# sub
# 案例: 将匹配到的阅读次数换成998
# 数据: "python = 997"

# re.sub("替换的匹配","想替换成的内容","被替换的内容")

str_data = "python = 10000"


# 生成一个新的字符
# new_data = re.sub("\d+", "998", str_data)
#
# print(new_data)
# print(str_data)

# 通过函数来修改值

def change_value(match):
    # 通过匹配的对象拿到对应的值
    value = match.group()
    # 值加1
    count_str = int(value) + 1

    return str(count_str)  # 必须返回字符串


print(re.sub("\d+", change_value, str_data))
python贪婪和非贪婪

Python里数量词默认是贪婪的(在少数语言里也可能是默认非贪婪),总是尝试匹配尽可能多的字符;非贪婪则相反,总是尝试匹配尽可能少的字符。

r 的作用
  • Python中字符串前面加上 r 表示原生字符串,数据里面的反斜杠不需要进行转义,针对的只是反斜杠

  • Python里的原生字符串很好地解决了这个问题,有了原生字符串,你再也不用担心是不是漏写了反斜杠,写出来的表达式也更直观。

>>> mm = "c:\\a\\b\\c"
>>> mm
'c:\\a\\b\\c'
>>> print(mm)
c:\a\b\c
>>> re.match("c:\\\\",mm).group()
'c:\\'
>>> ret = re.match("c:\\\\",mm).group()
>>> print(ret)
c:\
>>> ret = re.match("c:\\\\a",mm).group()
>>> print(ret)
c:\a
>>> ret = re.match(r"c:\\a",mm).group()
>>> print(ret)
c:\a
>>> ret = re.match(r"c:\a",mm).group()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'group'
>>>

建议: 如果使用使用正则表达式匹配数据可以都加上r,要注意r针对的只是反斜杠起作用,不需要对其进行转义

>>> ret = re.match(r"c:\\a",mm).group()
>>> print(ret)
c:\a

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/21383.html

(0)

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信