python使用正则表达式

article/2025/11/8 10:32:47

一、使用正则表达式步骤

1、寻找规律;

2、使用正则符号表示规律;

3、提取信息,如果每一个字符都能匹配,则匹配成功;一旦有匹配不成功的字符则匹配失败。

 

二、正则表达式中常见的基本符号

1.点号“.”一个点号可以代替除了换行符(\n)以外的任何一个字符,包括但不限于英文字母、数字、汉字、英文标点符号和中文标点符号。2.星号“*”一个星号可以表示它前面的一个子表达式(普通字符、另一个或几个正则表达式符号)0次到无限次。3.问号“?”问号表示它前面的子表达式0次或者1次。注意,这里的问号是英文问号。4.反斜杠“\”反斜杠在正则表达式里面不能单独使用,甚至在整个Python里都不能单独使用。反斜杠需要和其他的字符配合使用来把特殊符号变成普通符号,把普通符号变成特殊符号。如:“\n”。5.数字“\d”正则表达式里面使用“\d”来表示一位数字。再次强调一下,“\d”虽然是由反斜杠和字母d构成的,但是要把“\d”看成一个正则表达式符号整体。6.小括号“()”小括号可以把括号里面的内容提取出来。

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

import re

三、匹配的基本方法

在re模块中,通常使用三种方法,match,search和findall,下面对这三种方法进行简单的介绍:

1.match方法

re.match 尝试从字符串的起始位置匹配一个模式,匹配成功则返回的是一个匹配对象(这个对象包含了我们匹配的信息),如果不是起始位置匹配成功的话,match()返回的是空,
注意:match只能匹配到一个**

下面来看代码理解

s = 'python123python666python888'result = re.match('python', s)
print(result)  # <re.Match object; span=(0, 6), match='python'>
print(result.span())  # (0, 6)
print(result.group())  # python

1.通过span()提取匹配到的字符下标
2.通过group()提取匹配到的内容
而s字符串中有3个python的存在,match只能匹配到一个

下面我们改变一下s,得到不一样的结果

s = '1python123python666python888'result = re.match('python', s)
print(result)  #None

因为match从字符串的起始位置开始匹配,这里起始的第一个字符为1,所以匹配失败返回None.
那么我们要如何才能匹配到字符串中间我们想要的部分呢,这个时候就用到了search函数

2.search方法

re.search 扫描整个字符串,匹配成功则返回的是一个匹配对象(这个对象包含了我们匹配的信息)
注意:search也只能匹配到一个,找到符合规则的就返回,不会一直往后找
同样的,search也只能匹配到一个.
代码如下

s = '1python123python666python888'result = re.search('python', s)
print(result)  # <re.Match object; span=(1, 7), match='python'>
print(result.span())  # (1, 7)
print(result.group())  # python

当然,若是都找不到则返回None值

s = '1python123python666python888'result = re.search('python98', s)
print(result)  # None

*search方法虽然解决了match的从头匹配的弊端,但它也只能匹配到一个,这个时候我们就可以使用findall方法了 *

3.findall方法:

在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配的,则返回空列表

s = '1python123python666python888'result = re.findall('python', s)
print(result)  # ['python', 'python', 'python']

上面的三种方法看上去只能匹配到简单的字符串,也许我们觉得用一般的方法也可以办到:
比如字符串的index方法(也可以用循序)

print(s.index('python'))  # 1
print(s.index('python', 2))  # 10
print(s.index('python', 11))  # 19

那么正则表达式应该用在什么地方呢:

  • 判断用户注册帐号是否满足格式
  • 抓取页面中特定部分数据
  • 判断用户提交的邮箱的格式是否正确 等等等等
    那么我们就要了解元字符

 

四、元字符匹配规则

元字符:本身具有特殊含义的字符
先看几张常用的图片

单字符匹配: 如下

代表数量的元字符

表示边界的元字符

分组匹配

举例

下面我们来举一些例子

1.匹配账号:只能由字母和数字组成,长度为10位

import res = '1587022xzq'result = re.match('[0-9a-zA-z]{10}', s)
print(result)  # <re.Match object; span=(0, 10), match='1587022xzq'>

因为账号是从头到尾的,只需要匹配一次就行,所以我们可以使用match方法,但是上面的代码明显存在问题,比如将长度增加三位,它将依然能匹配到

s = '1587022xzqty'result = re.match('[0-9a-zA-z]{10}', s)
print(result)  # <re.Match object; span=(0, 10), match='1587022xzq'>

这是因为我们没有加上控制边界的元字符,下面是修改后正确的代码

s = '1587022xzqty'
result = re.match('^[0-9a-zA-z]{10}$', s)
print(result)  # None

解析:

  • (因为对于match来说,从头开始匹配,所以这里的^可以不加)
  • $的意思是匹配到字符串的结尾,
  • 账号的长度为10位是通过代表数量的元字符{10}来控制的

2.匹配qq号:长度为5-11位,纯数字组成,第一位不为0

s = '10086111222'
# 5 - 11 位
result = re.match('[1-9][0-9]{4,10}$', s)
print(result)  # <re.Match object; span=(0, 11), match='10086111222'>

解析:

  • 这里的代表数量的元字符{4,10}表示[0-9]出现的次数为[4,9]次(大于等于4,小于等于9),而第一位[0-9]占了一位数字,所以加起来是5-11位符合要求的qq号

我们可以简化一下[0-9]的写法,\d就可以代表纯数字

s = '10086111222'
# 5 - 11 位
result = re.match(r'[1-9]\d{4,10}$', s)
print(result)  # <re.Match object; span=(0, 11), match='10086111222'>

tip:这里在字符串前面加上r是为了取消转义,不然就需要写成 \d(虽然这里的\d实际上没有影响)

3.检索文件名 格式为 xxx.py

s = '1.py 2.png ssx.csv qaq.txt xzq.py'
#文件名格式: (数字字母_).py
result = re.findall(r'\w+\.py\b', s)
print(result)	# ['1.py', 'xzq.py']

解析:

  • \w代表 word ,及字母数字或下划线
  • +为控制数量 >=1
  • \b代表边界,这里如果前面不加上r的话\b就应该写成\b
  • 注意点.文件的格式为xxx.py 这里的.需要特别注意,因为在单字符匹配中


    所以我们需要使用 \ . 来表示我们所需要的.

4.匹配1-100的数字

s = '89'result = re.match(r'[1-9]?\d?$', s)
print(result)	# <re.Match object; span=(0, 2), match='89'>

这是第一步的思路,但是当我们把s改为100时就发现了错误

s = '100'result = re.match(r'[1-9]?\d?$', s)
print(result)  # None

改进之后的代码

s = '100'
r = '98'
z = '9'
q = '0'
result = re.match(r'[1-9]?\d?$|100$', s)
print(result)  
print(re.match(r'[1-9]?\d?$|100$', r))
print(re.match(r'[1-9]?\d?$|100$', z))
print(re.match(r'[1-9]?\d?$|100$', q))
''' <re.Match object; span=(0, 3), match='100'> <re.Match object; span=(0, 2), match='98'> <re.Match object; span=(0, 1), match='9'> <re.Match object; span=(0, 1), match='0'> '''

5.验证输入的邮箱

# 验证输入的邮箱 163 126 qq 前面至少五位,至多11位
email = '738473800@qq.com'
result = re.match(r'\w{5,11}@(163|126|qq)\.(com|cn)$', email)
print(result)  # <re.Match object; span=(0, 16), match='738473800@qq.com'>

注意:括号和方括号的区别
(qq|163|126)代表的是qq或163或126
[qq|163|126]代表的是q1236这几个符号

6.分组提取匹配爬虫电话号码

比如我们用爬虫爬到了一组数据
里面有一组数据是xxxx-xxxxxxxx
前面包含3/4个数字,后面包含8个数字
下面将他们取出,这里我们用到了分组,(小括号)

# 爬虫
phone = '010-12345678'
result = re.match(r'(\d{3}|\d{4})-(\d{8})$', phone)
print(result)  # <re.Match object; span=(0, 12), match='010-12345678'>
print(result.group())  # 010-12345678
print(result.group(1))  # 010
print(result.group(2))  # 12345678

一个小括号为一个分组,可以用group提取出来

7.匹配html标签内容

# 爬虫
html标签的格式形如 <xxx>y</xxx>	y为我们要提取的内容
s = '<h1>hello</h1>'
result = re.match('<[0-9A-z]+>(.+)</[0-9A-z]+>$', s)
print(result)  # <re.Match object; span=(0, 14), match='<h1>hello</h1>'>
print(result.group(1))  # hello

表面上看这样没什么问题,但如果更改s如下就出现了问题

# 爬虫
s = '<html>hello</h1>'
result = re.match('<[0-9A-z]+>(.+)</[0-9A-z]+>$', s)
print(result)  # <re.Match object; span=(0, 16), match='<html>hello</h1>'>
print(result.group(1))  # hello

所以改进,利用分组来判断

# 爬虫
s = '<html>hello</h1>'
s2 = '<html>hello</html>'
result = re.match(r'<([0-9A-z]+)>(.+)</\1>$', s)
print(result)  # None
result = re.match(r'<([0-9A-z]+)>(.+)</\1>$', s2)
print(result)  # <re.Match object; span=(0, 18), match='<html>hello</html>'>
print(result.group(1))  # html
print(result.group(2))  # hello

解析:这里使用\1代表与第一个分组相同
拓展:起名字

# 取名字 (?P<名字>正则) (?P=名字)

看似繁琐了一点,但是在遇到复杂的情况,比如多重标签嵌套,或者其他情况下的时候通过取名分组的方法十分实用,不容易出错

# 取名字 (?P<名字>正则) (?P=名字)
s = '<html>hello</h1>'
s2 = '<html>hello</html>'
result = re.match(r'<(?P<name1>\w+)>(.+)</(?P=name1)>$', s)
print(result)  # None
result = re.match(r'<(?P<name1>\w+)>(?P<msg>.+)</(?P=name1)>$', s2)
print(result)  # <re.Match object; span=(0, 18), match='<html>hello</html>'>
print(result.group('name1'))  # html
print(result.group('msg'))  # hello

(3).sub方法

类似于replace替换方法rre.sub(正则表达式,替换成什么,要替换的字符串)

s1 = 'java:90 python:95 html:89'
result = re.sub(r'\d+', '90', s1)
print(result)  # java:90 python:90 html:90

不过第二个参数位置可以放函数
比如把取出来的数字都加一,函数可以理解为找到一个匹配的值就执行一次函数

def func(num):a = num.group()b = int(a) + 1return str(b)s1 = 'java:90 python:95 html:89'
result = re.sub(r'\d+', func, s1)
print(result)  # java:91 python:96 html:90

(4).split方法

split切割,根字符串的spilt类似,但是更加灵活

s1 = 'java:90,python:95,html:89'
result = re.split(r'[,:]', s1)
print(result)  # ['java', '90', 'python', '95', 'html', '89']

(5).贪婪与非贪婪

正则默认都是用贪婪模式去匹配数据的,就是尽可能多的匹配符合要求的数据
非贪婪模式下,始终找最短匹配


加上?之后就变成非贪婪模式

s1 = 'abc1123avc'
result = re.findall(r'[A-z]+\d+', s1)
print(result)  # ['abc1123']
s1 = 'abc1123avc'
result = re.findall(r'[A-z]+\d+?', s1)
print(result)  # ['abc1']

http://chatgpt.dhexx.cn/article/iirkxjKr.shtml

相关文章

Python 正则表达式

1.正则表达式的定义: 正则表达式是对字符串进行解析&#xff08;获取一大串字符串信息中&#xff0c;你想要的部分&#xff09;。 正则表达式是一种文本模式&#xff0c;模式描述在搜索文本时要匹配的一个或多个字符串。 正则表达式&#xff0c;又成正规表示式&#xff0c;正规…

python正则表达式详解

正则表达式是一个很强大的字符串处理工具&#xff0c;几乎任何关于字符串的操作都可以使用正则表达式来完成&#xff0c;作为一个爬虫工作者&#xff0c;每天和字符串打交道&#xff0c;正则表达式更是不可或缺的技能&#xff0c;正则表达式的在不同的语言中使用方式可能不一样…

详解Python正则表达式(含丰富案例)

前言&#xff1a;正则表达式在网络爬虫、数据分析中有着广泛使用&#xff0c;掌握正则表达式能够达到事半功倍的效果。本文详细介绍正则表达式中各种规则及其符号含义&#xff0c;并结合Python中的Re库进行演示&#xff0c;由浅入深&#xff0c;即学即练即用&#xff0c;内容丰…

Python超详细的正则表达式

目录 介绍 常用的正则表达式匹配规则表格 1.match() .group() 常用知识点 1.通用匹配 2.贪婪与非贪婪 3.修饰符 4.转义匹配 2.search() 3.findall() 4.sub() 总结 Hello大家好我是&#xff0c;PYmili&#xff01;今天给大家带来正则表达式的使用教程即匹配规则表格…

Python正则表达式(一看就懂)

目录 哈喽O(∩_∩)O&#x1f604; 什么是正则表达式(⊙_⊙) 简单说&#xff0c;正则表达式是… 正则表达式怎么用❓ sreach的用法&#x1f34a; 匹配连续的多个数值&#x1f349; 字符""重复前面一个匹配字符一次或者多次&#x1f349; 字符"*"重复前…

Python正则表达式详解 (超详细,看完必会!)

正则表达式详解 正则表达式 英文名称叫 Regular Expression简称RegEx&#xff0c;是用来匹配字符的一种工具&#xff0c;它常被用在网页爬虫&#xff0c;文稿整理&#xff0c;数据筛选等方面&#xff0c;最常用的就是用在网页爬虫&#xff0c;数据抓取。 一、正则表达式的各种…

Python 正则表达式详解(建议收藏!)

目录 match 匹配字符串 单字符匹配 . 匹配任意一个字符 \d 匹配数字 \D 匹配非数字 \s 匹配特殊字符&#xff0c;如空白&#xff0c;空格&#xff0c;tab等 \S 匹配非空白 \w 匹配单词、字符&#xff0c;如大小写字母&#xff0c;数字&#xff0c;_ 下划线 \W 匹配非…

Android工程中方法数超过65536解决方法(Kotlin)

Android Studio报错&#xff1a; The number of method references in a .dex file cannot exceed 64K. Caused by: com.android.tools.r8.utils.AbortException: Error: Cannot fit requested classes in a single dex file (# methods: 68815 > 65536) 解决方案 build.…

postman/EOLINKER测试报错 RangeError:Port should be 0 and 65536. Received 80892.

postman/EOLINKER测试报错 RangeError&#xff1a;Port should be > 0 and < 65536. Received 80892. RangeError&#xff1a;范围错误 RangeError是当一个只超出有效范围时发生的错误。主要的有几种情况&#xff0c;第一是数组长度为负数&#xff0c;第二是Number对象…

Android Studio Cannot fit requested classes in a single dex file (# methods: 72633 > 65536)解决办法

今天在Android Studio中构建Android工程时&#xff0c;出现了这样报错&#xff1a;“Cannot fit requested classes in a single dex file (# methods: 72633 &#xff1e; 65536)” 在网上找了一圈儿&#xff0c;总结个简单快速的解决方法 问题&#xff1a; Cannot fit req…

计算机端口号65536,65536端口能不能用

楼主asdd3000(asdd) 16位计算机端口65536个,32位计算机端口是65536/2个还是65536*2个?为什么? 问题点数:10、回复次数:20 Top 1 楼EvilOctal(冰血封情) 回复于 2004-04-08 20:41:04 得分 0 这个问题我真的不太清楚. 但是 好象和位数没关系吧? 服务端口是国际组织规定的,不是…

为什么89C51单片机里面有TH0=(65536-50000)/256;TL0=(65536-50000)%256;

由于89C51的晶振频率为12MHZ&#xff0c;机器周期是1us,则每1us产生一次计数&#xff0c;例如需要进行50ms的计时&#xff0c;对机器周期进行50000计数就可以得到&#xff0c;T0可以对机器周期进行65536次计数&#xff0c;为了不让T0溢出&#xff0c;我们需要对定时器/计数器赋…

NXP MCUXPresso - cc1plus.exe: out of memory allocating 65536 bytes

文章目录 NXP MCUXPresso - cc1plus.exe: out of memory allocating 65536 bytes概述实验结论补充END NXP MCUXPresso - cc1plus.exe: out of memory allocating 65536 bytes 概述 在尝试迁移 openpnp - Smoothieware project 从gcc命令行 MRI调试方式 到NXP MCUXpresso工程…

65536 65535 65534

65536 65535 65534 通常在导入模型的时候会遇到65534的限制&#xff0c;比如Unity里的“Meshes may not have more than 65534 vertices or triangles at the moment”提示。开起来像是2的16次方&#xff0c;但为什么不是65536&#xff1f;65536和65535会有什么问题&#xff1…

Eclipse中65536的解决办法

最近在做项目的时候&#xff0c;发现引入的第三方工程太多&#xff0c;无法打包成app文件了。如下 遇到这种问题怎么办呢&#xff1f;&#xff1f;&#xff1f;我们先看问题描述&#xff1a;方法数不在0-65536内&#xff0c;dalvik。。错误&#xff0c;不懂&#xff0c;还是先百…

Android中65536问题剖析

问题出现的原因是因为导入融云通信的包后&#xff0c;突然提示&#xff1a; Error:The number of method references in a .dex file cannot exceed 64K. Learn how to resolve this issue at https://developer.android.com/tools/building/multidex.html。 解决办法&#xf…

数据类型

强类型语言 强类型语言是一种强制类型定义的语言&#xff0c;一旦某一个变量被定义类型&#xff0c;如果不经过强制转换&#xff0c;则它永远就是该数据类型了&#xff0c;强类型语言包括Java、.net 、Python、C等语言&#xff0c;要求变量的使用要严格符合规定&#xff0c;所有…

C语言自己写代码实现的strcmp函数

我们在面试的时候&#xff0c;经常会被笔试实现C语言系统函数&#xff0c;比如strcmp函数&#xff0c;主要考察大家的C语言功底&#xff01; #include <assert.h> #include <stdio.h>int MyStrCmp(const char* str1, const char* str2) {assert((str1 ! NULL) &a…

用指针实现strcmp函数功能

strcmp函数的原理&#xff1a; 将两个字符串&#x1f50d;&#xff08;s1&#xff0c;s2&#xff09;的元素ascii码依次比较&#xff0c;直到遇到最短字符串的‘\0’&#xff0c;返回最后一个元素ascii码比较结果。 指针实现方式&#xff1a; 通过定义两个char*指针&#x1f5…

C语言中的strcmp函数的作用是什么,c语言strcmp函数用法是什么?

c语言strcmp函数用法&#xff1a;语法结构为【int strcmp(char *str1, char *str2)】&#xff0c;比较字符串str1和str2是否相同&#xff0c;如果相同则返回0&#xff0c;如果不同&#xff0c;在不同的字符处如果str1的字符大于str2字符&#xff0c;则返回负1。 c语言strcmp函数…