【Python】正则

特殊字符转义

以下字符都需要用 反斜线(\)来进行特殊字符的转义。

\n - 换行符
\t - 制表符
\ - 反斜线本身
. - 点号(任意单个字符)
星号(0次或多次重复前面的元素)
加号(1次或多次重复前面的元素)
? - 问号(零次或一次重复前面的元素)
[] - 方括号内的任何字符集合
() - 分组操作符
{} - 花括号内指定数量的重复次数

起因,python正则匹配,从'你好aaa+'匹配‘aaa+’,我就想完整的匹配aaa+,但是实际效果是'你好a'这种的也能匹配上。

debug发现原来+在正则中是特殊字符。如果要匹配 + 字符本身,你需要使用反斜杠 \ 对它进行转义。即遇见 + 的pattern用 /+ 来替换,

modified_string = original_string.replace("+", "/+")

‘aaa+’被解释为:匹配前面的字符 'aaa' 一次或多次。

import re

re.search('aaa+', 'a') # none

re.search('aaa+', 'aaab') # <_sre.SRE_Match object; span=(0, 3), match='aaa'>

re.search('aaa+', 'ab') # none

re.search('aaa+', 'aab') # none

re.search('aaa+', 'aaaaaab')  # <_sre.SRE_Match object; span=(0, 6), match='aaaaaa'>

re.match() 与 re.search() 的区别

1. `re.match()`:
   - `re.match()` 用于从字符串的起始位置开始匹配正则表达式。
   - 如果匹配成功,`re.match()` 返回一个匹配对象;如果匹配失败,它返回 `None`。
   - 它只匹配字符串的第一个子串,也就是说,它不会扫描整个字符串,而是在找到第一个匹配项后停止。

re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none。

2. `re.search()`:
   - `re.search()` 用于在字符串中扫描正则表达式,并返回第一个匹配项。
   - 如果匹配成功,`re.search()` 返回一个匹配对象;如果匹配失败,它返回 `None`。
   - 它会扫描整个字符串,直到找到第一个匹配项为止。

简而言之,`re.match()` 通常用于检查字符串的起始部分是否与正则表达式匹配,而 `re.search()` 用于在整个字符串中查找匹配项。下面是一个示例,展示这两个函数的区别:

总结:search()更符合需求。

import re

# 示例字符串
text = "这是一个测试字符串,包含多个部分。"

# 正则表达式
pattern1 = r'测试'
pattern2 = r'多个部分'

# 使用re.match()
match1 = re.match(pattern1, text)
match2 = re.match(pattern2, text)

print(f"match1: {match1}") # match1: None
print(f"match2: {match2}") # match2: None


# 使用re.search()
search1 = re.search(pattern1, text)
search2 = re.search(pattern2, text)

print(f"search1: {search1}") # search1: <_sre.SRE_Match object; span=(4, 6), match='测试'>
print(f"search2: {search2}") # search2: <_sre.SRE_Match object; span=(12, 16), match='多个部分'>

re.search()与 re.findall() 的区别

re.search(pattern, string, flags=0)

  • re.search() 函数用于搜索字符串中是否有匹配正则表达式的部分。
  • re.search() 通常用于检查一个字符串是否包含某个模式,或者找到匹配模式的第一个位置。

re.findall(pattern, string, flags=0)

  • re.findall() 函数用于找到字符串中所有匹配正则表达式的部分,并返回一个列表。
  • 它返回所有匹配项的列表,如果没有找到任何匹配项,则返回空列表。
  • re.findall() 通常用于提取字符串中所有匹配模式的部分。

总结一下,re.search() 用于查找单个匹配项,而 re.findall() 用于查找所有匹配项。

如果你只需要找到第一个匹配项,可以使用 re.search();如果你需要找到所有匹配项,应该使用 re.findall()。

注意: match 和 search 是匹配一次 findall 匹配所有。

 re.findall()

matches = re.findall(pattern, str)
text = '这是一款项链含有很多配件例如吊坠你肯定觉得很好'
res = re.findall(r'项链|吊坠', text)
res # ['项链', '吊坠']

re.sub()

# 将str中匹配到的pattern部分替换为''

new_str = re.sub(pattern, '', str)

re.compile()

compile2个()是什么意思?组合的意思,括号1+括号2组成一个匹配模式。

e.g. case分析

(.卖店|(官方)?旗舰店|专营店|专卖)

  • . 表示任何单个字符(除了换行符)。
  • 卖店、(官方)?旗舰店、专营店 或 专卖:这些是不同的选项,匹配与之相匹配的字符串。
  • 括号 () 用于组匹配,() 中的表达式可以作为一个组一起被引用。
  • (官方)? 表示“官方”这个词是可选的,? 表示前面的元素出现零次或一次。
pattern = re.compile("(.{0,30})(.卖店|(官方)?旗舰店|专营店|专卖)")


# |是或的意思,“.卖店” or “(官方)?旗舰店” 都匹配了一次
# (.{0,30}) 是在“.卖店” or “(官方)?旗舰店”,前最多出现30个字符。
mystr = '官方旗舰店是卖店'
find_all = re.findall(pattern, mystr) 
find_all # [('官方旗舰店', '是卖店', '')]




# '这是一'????
mystr = '这是一个卖店'
find_all = re.findall(pattern, mystr)
find_all # [('这是一', '个卖店', '')]


# “.卖店” or “专营店” 都匹配了一次
mystr = '专营店是卖店'
find_all = re.findall(pattern, mystr)
find_all # [('专营店', '是卖店', '')]



# 不 从哪来?
mystr = '专卖不是卖店'
find_all = re.findall(pattern, mystr)
find_all # [('专卖不', '是卖店', '')]



# .是必须要匹配一个字符的
mystr = '卖店这是一个'
find_all = re.findall(pattern, mystr)
find_all # []


mystr = '旗舰店是卖店这不是官方'
find_all = re.findall(pattern, mystr)
find_all # [('旗舰店', '是卖店', '')]

case2, 其实没太理解

第一个()感觉有和没有没区别。

但是匹配的字符串,必须要以第二个括号里的词结束。

pattern = re.compile("(去|厨房卫浴|^)(.卖店|(官方)?旗舰店|专营店|专卖)") # 2个()什么意思?


mystr = '去迭戈'
find_all = re.findall(pattern, mystr)
find_all # []
# ------------------------------------------------------------------


mystr = '去迭戈专卖'
find_all = re.findall(pattern, mystr)

print(f"find_all: {find_all}")
print(f"re: {re.search(pattern, mystr)}")
find_all: [('去', '专卖', '')]
re: <_sre.SRE_Match object; span=(0, 3), match='去专卖'>
# ------------------------------------------------------------------


mystr = 'c去迭戈专卖'
find_all = re.findall(pattern, mystr)

print(f"find_all: {find_all}")
print(f"re: {re.search(pattern, mystr)}")

find_all: [('c去迭戈', '专卖', '')]
re: <_sre.SRE_Match object; span=(0, 6), match='c去迭戈专卖'>
# ------------------------------------------------------------------


mystr = '专卖'
find_all = re.findall(pattern, mystr)

print(f"find_all: {find_all}")
print(f"re: {re.search(pattern, mystr)}")
find_all: [('', '专卖', '')]
re: <_sre.SRE_Match object; span=(0, 2), match='专卖'>

常用匹配符

模式描述
^匹配字符串开头
$匹配字符串结尾
.匹配任意字符
*匹配前面的字符零次或多次
+匹配前面的字符一次或多次
?匹配前面的字符零次或一次
[]匹配括号中列举的任意一个字符
[^]匹配除了括号中列举的字符以外的任意一个字符

其他匹配1-n个,见python str 正则匹配两个标点符号之间的内容 python正则匹配多个数字_lanhy的技术博客_51CTO博客

^说明

^ 是一个特殊字符,它表示“匹配输入字符串的开始位置”。具体来说,当 ^ 与一个字符集或字符串前缀相结合时,它表明匹配必须从该字符集或字符串的开始处发生。

以下是一些使用 ^ 的例子:

  1. ^abc:匹配任何以 "abc" 开头的字符串。
  2. ^A:匹配任何以大写字母 'A' 开头的字符串。
  3. ^[a-z]:匹配任何以小写字母开头的字符串。
  4. ^[0-9]:匹配任何以数字开头的字符串。

需要注意的是,^ 只在正则表达式的第一个字符位置有特殊含义。如果在正则表达式中它不是第一个字符,它就仅仅是一个普通的字符,而不是表示行的开始。例如,在 a^b 中,^ 只是字符 '^' 本身,而不是特殊符号。

*、+、?的用法

* :——表示匹配前面的字符0个或多个;
+ :——表示前面的字符1个或多个;
?:——(1)放在其他字符后面:表示匹配0次或1次;
   (2)放在*、+后面:表示匹配尽可能少的字符


举例,

字符串fooooo:
fo*和fo+:表示匹配整个字符串
fo+?:表示匹配fo
fo*?:表示匹配f

举例

实践1:匹配12g

pattern = r"\d+\s*[Gg][Bb]?"  # 256g, 12g

实践2:匹配12g+12g, 12gb+12gb, 12g+1

pattern = r"\d+\s*[g]?[b]?\+\d+\s*[Gg]?[Bb]?"

希望匹配12g+8, 126gb+8g, 8+126等字符串。

结论

pattern1 = r"\d+\s*[g]?[b]?\+\s*\d+\s*[Gg]?[Bb]?"  # '128gb+256gb', '8+256g', '8+128'
matches = re.findall(pattern1, text) # list
print('matches:', matches)
 
 
pattern2 = r"\d+\s*[Gg][Bb]?"  # 256g, 12g

pattern = r"\d+\s*[mm]" # 20mm
  • \d+ 匹配一系列数字。
  • \s* 匹配零个或多个空格。
  • \+? 匹配零个或一个加号。
  • \d+ 再次匹配一系列数字。
  • \s* 再次匹配零个或多个空格。
  • [Gg] 匹配字母 "G" 无论大小写。
  • [Bb]? 匹配零个或一个字母 "B" 无论大小写。

实践3:判断字符串时候含有list中的某个词

rule_set # 很长的一个含各种关键词的set(去重)

rule_pattern = re.compile("|".join(rule_set))
find_rule = re.findall(rule_pattern, text)
if find_rule:
	print("匹配到的关键词", find_rule[0])

实践4:匹配整数+小数

pattern = r'\d+\.?\d*'  # 匹配小数

text = '今天周二5.0'
digit = re.search(pattern, text)
digit.group() # '5.0'



text = '今天周二5'
digit = re.search(pattern, text)
digit.group() # '5'



text = '今天1.325周二'
digit = re.search(pattern, text)
digit.group() # '1.325'

实践5:匹配模型中加数字

{m,n} 是一个量词,用来指定前面的元素出现的次数范围

所以,(.{0,30}) 表示匹配任意0到30个除换行符之外的任意字符。这意味着这个表达式可以匹配一个空字符串,或者任意数量(最多30个)的任意字符。

e.g. 匹配“今日特价”,今日和特价中间最多出现0-2个字符。

pattern = re.compile("今日.{0,2}特价")


text = '今日特价'
re.search(pattern,text) # <_sre.SRE_Match object; span=(0, 4), match='今日特价'>

text = '今日你好特价'
re.search(pattern,text) # <_sre.SRE_Match object; span=(0, 6), match='今日你好特价'>


text = '今日你好好特价'
re.search(pattern,text) # 无


实践6:非汉字部分全部剔除*

pattern = re.compile(r'[^\u4e00-\u9fff]') # 用于匹配任何不在汉字范围内的 Unicode 字符。


text = '198301周二:'
text_clear = re.sub(pattern, '', text).strip() # 是所有非汉字的字符
text_clear # '周二'


text = ':你好:'
text_clear = re.sub(pattern, '', text).strip() # 是所有非汉字的字符
text_clear # '你好'

  • 9
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值