Python3:正则表达式

正则表达式

  • 正则表达式基本
  • 正则表达式:分组

正则表达式基本

# 正则表达式
"""
1、正则表达式的定义:
正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特殊字符、及这些特定字符的组合,组成一个”规则字符串“,这个”规则字符串“用来表达对字符串的一种过滤逻辑。

正则表达式是对字符串(包括普通字符(类如a-z之间的字母)和特殊字符(成为”元字符“))操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一
个”规则字符串“,这个“规则字符串”用来表达对字符串的一种过滤逻辑。正则表达式是一种文本模式,模式描述在搜索文本时要匹配一个或者多个字符串。

正则表达式,又称正则表示式、正规表示式、规则表达式、常规表示法(英文:Regular Expression,在代码中regex、regexp或RE)是计算机科学一种概念。正则表达式使用单个
字符串来描述、匹配一系列匹配某个句法规则的字符串。在很多文本编辑器里,正则表达式通常被用来检索、替换哪些匹配某个模式的文本。

Regular Expression ”Regular“ 一般被翻译为”正则“、”正规“、”常规“。此处的”Regular“即是”规则“、”规律”的意思 Regular Expression即“描述某种规则的表达式”之意

正则在所有语言中都有的内容

2、正则表达式的作用和特点
给定一个正则表达式和一个字符串,可以达到如下目的
1)给定的字符串是否符合正则表达式的过滤逻辑(成为“匹配”)
2) 可以通过正则表达式,从字符串中获取我们想要的特定部分

正则表达式的特点:
1)灵活性、逻辑性和功能性非常强
2)可以迅速用极简单的方法达到字符串的复杂控制
3)对于刚接触的人比较晦涩难懂

场景:
如何判断一个字符串是手机号?

判断邮箱为163或者126的所有邮件地址
假如你在写一个爬虫,你得到了一个网页的HTML源码,其中有一段

s = "

hello world

" 你想要把这个hello world 提取出来,但你这时如果只会python 的字符串处理,那么第一反应可能是 s = "

hello world

" start_index = s.find('

') python re模块 \A:表示从字符串的开始处匹配 \Z: 表示从字符串的结束处匹配,如果存在换行,只匹配到换行前的结束字符串 \b: 匹配一个单词边界,也就是指单词和空格间的位置。例如,‘py\b’ 可以匹配”python“中的”py“,但不能匹配”openpyxl“中的”py“ \B: 匹配非单词边界。”py\b“ 可以匹配”openpyxl“ 中的”py“, 但不能匹配”python“ 中的”py“。 \d:匹配任意数字,等价于[0-9]. digit \D:匹配任意非数字字符,等价于[^\d] not digit \s:匹配任意空白字符,等价于[\t\n\r\f]. space \S:匹配任意非空白字符,等价于【^\s】. \w:匹配任意字母数字及下划线,等价于[a-zA-Z0-9_] word \W:匹配任意非字母数字及下划线,等价于[^\w] \\:匹配原意的反斜杠\。 ".":用于匹配换行符(\n)之外的字符。 (任意字符除了\n) 注意: . 必须被转义否则会匹配任意字符 建议\. "^":方括号里边是非; 用于匹配字符串的开始 "$":用于匹配字符串的末尾(末尾如果有换行符\n,就匹配\n前面的那个字符),即行尾 "*" 用于将前面的模式匹配0此或多次(贪婪模式:即尽可能多匹配) "+" 用于将前面的模式匹配1此或者多次(贪婪模式) "?" 用于将前面的模式匹配0此或者1次(贪婪模式) "*?,+?,??" 即上面三种特殊字符的非贪婪模式(尽可能少的匹配) “{m,n}” 用于将前面的模式匹配m次到n次(贪婪模式),即最小匹配m次,最大匹配n次。 “{m,n}?” 即上面“{m,n}”的非贪婪版本 \\: '\'是转义字符,在特殊字符前面加\,特殊字符就失去了其所代表的含义,比如\+就仅仅代表加号+本身 []:用于标识一组字符,如果^是第一个字符,则标示的是一个补集。比如[0-9]标示所有的数字,[^0-9]标识除了数字外的字符。 |:比如A|B用于匹配A或者B (...):用于匹配括号中的模式,可以在字符串中检索或匹配我们所需要的内容。 [] :表示范围 [abc][a-z] [a-z*&]或者的关系 、表示单个字母而不是但单词 |:或者 ():# (qq|163|126) 小括号表示整体返回的或者 qq 或者163 或者126 量词: * >=0 + >=1 ? 0,1 {m} 固定几位 {m,} >=m {m,n} m<= x <=n 正则符号: 注意:  \d [a-z] 指标是一个字符 . 必须被转义否则会匹配任意字符 建议\. Python里数量词默认是贪婪模式(在少数语言里也可能是默认非贪婪),总是尝试匹配尽可能多的字符; 非贪婪则相反,总是尝试匹配尽可能少的字符。 在”*“,”?“,"+" {m,n}后面加?,使贪婪变成非贪婪 """ # 使用正则表达式验证qq的合法性验证 qq = input("请输入你的QQ号码:") if len(qq) >= 5 and not qq.startswith("0"): # qq[0] !='0' print("qq号码是合法的") else: print("不合法") # 正则表达式 import re message = 'sanduo lily lucy' pattern = re.compile('lily') # 匹配失败:none # pattern = re.compile('sanduo') # 匹配成功: result = pattern.match(message) # 没有匹配返回空(从头开始匹配) print(result) # 正则模块的方法re : match re_match = re.match("sanduo", message) # 从头开始匹配,没有就返回None print(re_match) # re_search = re.search("lily", message) # #匹配的是整个字符串(从头一直找到尾) print(re_search) print(re_search.span()) # (7, 11) span 是匹配的位置;翻译一个位置 print(re_search.groups()) # () 空元组 print(re_search.group()) # 使用group提取匹配的数据 # a2b h6k msg = 'bckshsaa cinlwn&nel*223jluin8819jhunk21nlini' result = re.findall('[a-z][0-9]+[a-z]', msg) print(result) # ['n8819j', 'k21n'] # 用户名可以是字母或者数字,不能是数字开头,用户长度必须是6位以上['a-zA-Z\[d|a-zA-Z]{5,}'] name1 = '0Asanduo123' name2 = "SanDUuo123" name3 = "SanDUuo123#&" # 必须用$符号结尾 name4 = "123SanDUuo123#&" # 必须用^符号限制开始 name1_result = re.match("[a-zA-Z][0-9a-zA-Z]{5,}", name1) # name1_result None print("name1_result", name1_result) name2_result = re.match("[a-zA-Z][0-9a-zA-Z]{5,}", name2) # print("name2_result", name2_result) name3_result = re.match("[a-zA-Z][0-9a-zA-Z]{5,}$", name3) # match $ 限定结尾;name3_result None print("name3_result", name3_result) name4_result = re.search("^[a-zA-Z][0-9a-zA-Z_]{5,}$", name4) # 如果是search:^ 限定开始 name4_result None print("name4_result", name4_result) name4_result = re.search("^[a-zA-Z]\w{5,}$", name4) # 如果是search:^ 限定开始 name4_result None print("name4_result", name4_result) # qq号码校验 5-11位 开头不能是0 qq = "1008001917" qq_match = re.match("^[1-9][0-9]{4,10}$", qq) print(qq_match) # msg = "aa.py ab.txt bbb.py cc.py DD*py" msg_border = re.findall("py\\b", msg) # py\\b 等价 r"py\b" print(msg_border) # ['py', 'py', 'py', 'py'] msg_border = re.findall(r"\w*\.py\b", msg) # r不发生转义 . 必须被转义否则会匹配任意字符 建议\. print(msg_border) # ['aa.py', 'bbb.py', 'cc.py'] # 手机号码正则 phone = "18700191127" match_none = re.match(r"^1[35789]\d{9}$", phone) print("match_none", match_none) # match_none print("贪婪非贪婪操作".center(20, "*")) msg = "abc123adrd" msg_match = re.match(r"[a-z]+\d+", msg) # 贪婪模式:默认 只要后面有符合条件的,就往后面取 print(msg_match) # msg_match = re.match(r"[a-z]+\d+?", msg) # 非贪婪模式:将贪婪模式变成非贪婪模式 加 “?” 只要发现就停止了,不会在给后面匹配了 print(msg_match) # path = '' img_match = re.match(r', path) print(img_match) print(img_match.groups()) print(img_match.group(1))# http://t14.baidu.com/it/u=963524666,2960549705&fm=224&app=112&f=JPEG?w=500&h=500 print(img_match.group(2)) # http://t14.baidu.com/it/u=963524666,2960549705&fm=224&app=112&f=JPEG?w=500&h=500 # 链接有逗号报错:requests.exceptions.InvalidSchema: No connection adapters were found for image_url = img_match.group(1) import requests response = requests.get("http://bpic.588ku.com/webpage_pic/22/06/29/b5a3b7ea8e66fa74090d7e1269a2b478.jpg") # response = requests.get(image_url) # requests.exceptions.InvalidSchema: No connection adapters were found for print(response) with open('aa.jpg', 'wb') as write_stream: # print(response) write_stream.write(response.content)

正则表达式:分组

# 分组匹配
"""
group:()  两种:(number 、name)
    分组:() -->result.group(1) 获取组中的匹配内容   名字匹配
        分组的时候可以结合 |
            phone = "010-12345667"
            match_phone = re.match(r"(\d{3}|\d{4})-(\d{8})$", phone)
            print(match_phone)  # 
    不需要引用分组的内容:引用匹配
        msg = "

abc

" result_msg = re.match(r"<([0-9a-zA-Z]+)><([0-9a-zA-Z]+)>(.+)$", msg) print(result_msg) # print(result_msg.group(1)) 引用分组匹配的内容: 1、number (标签少) \number 引用第number组的内容 msg = "

abc

" result_msg = re.match(r"<([0-9a-zA-Z]+)><([0-9a-zA-Z]+)>(.+)$", msg) 2、?P<名字>(标签多) s = "

hello world

" s_match = re.match(r"<(?P\w+)><(?P\w+)><(?P\w+)>(.+)", s) print(s_match) # print(s_match.group(1)) re模块: match:从头匹配到尾,只匹配一次 search:找到第一个就停止查找,并返回:只匹配一次 findall:查找所有 sub(正则表达式、需要替换的新内容或者函数、原字符串):替换 split:字符串中搜索如果遇到 空格 就分割,将分割的类容都保存到列表中 re_split = re.split(r" ", "java:80 python:70") # 空格 print(re_split) # ['java:80', 'python:70'] split(pattern,str)-->[] """
import re # 匹配数字0-100 n = "50" re_match = re.match(r"[1-9]?\d", n) print(re_match) # nu = "09" re_match = re.match(r"[1-9]?\d", nu) print(re_match) # 有问题 num = "100" re_match = re.match(r"[1-9]?\d", num) # print(re_match) re_match = re.match(r"[1-9]+\d*", num) # print(re_match) # # 改进版 new_num = "100" re_match = re.match(r"[1-9]?\d?$|100$", new_num) # print(re_match) # # 验证邮箱163 qq 126 email = "[email protected]" match_email = re.match(r"\w+@(qq|163|126).com$", email) # (qq|163|126) 小括号表示整体返回的或者 print(match_email) # # 邮件名称必须大于5位,小于20位 email = "[email protected]" match_email = re.match(r"\w{5,20}@(qq|163|126)\.com$", email) # (qq|163|126) 小括号表示整体返回的或者 print(match_email) # print("正则分组操作".center(20, "*")) # group # a2b h6k msg = 'bckshsaa cinlwn&nel*223jluin8819jhunk21nlini' result = re.search(r"[a-z]\d+[a-z]", msg) # search只要找到就停下了 # print(result) print(result.group()) # ['n8819j', 'k21n'] result = re.findall(r"[a-z]\d+[a-z]", msg) # findall查找字符串中所有 print(result) # ['n8819j', 'k21n'] result = re.match(r"[a-z]\d+[a-z]", msg) # search只要找到就停下了 print(result) # print(result.group()) # ['n8819j', 'k21n'] # qq号码验证5-11位;0不能开头 qq = "1234" qq = "100799979" result = re.match(r"^[1-9]\d{4,10}$", qq) # print(result) # 分组起名:用起名的方式处理 (?P<名字>正则) 引用(?P=名字) s = "

hello world

"
s_match = re.match(r"<(?P\w+)><(?P\w+)><(?P\w+)>(.+)", s) print(s_match) # print(s_match.group(1)) print(s_match.group(2)) print(s_match.group(3)) print(s_match.group(4)) # 使用数字 分组 msg = "

abc

"
result_msg = re.match(r"<([0-9a-zA-Z]+)><([0-9a-zA-Z]+)>(.+)$", msg) print(result_msg) # print(result_msg.group(1)) print(result_msg.group(2)) print(result_msg.group(3)) # sub re_sub = re.sub(r"\d+", "100", "java:80 python:70") print(re_sub) # java:100 python:100 # 函数替换 def func(temp): nm = temp.group() new_nm = int(nm) + 10 return str(new_nm) res_sub = re.sub(r"\d+", func, "java:80 python:70") print(res_sub) # java:90 python:80 re_split = re.split(r"[,: ]", res_sub) # 逗号、冒号、空格 print(re_split) # ['java', '90', 'python', '80'] re_split = re.split(r" ", "java:80 python:70") # 空格 print(re_split) # ['java:80', 'python:70'] # 不是以 4、7 结尾的收集号码 11位 phone = "18700191128" match_phone = re.match(r"1\d{9}[0-35-68-9]$", phone) print(match_phone) # print(match_phone.group()) # 18700191128 # 爬虫:分组 phone = "010-12345667" match_phone = re.match(r"(\d{3}|\d{4})-(\d{8})$", phone) print(match_phone) # # 分别提取 # () 表示分组,groups(1):表示提取第一组的内容,groups(2)表示第二组的内容 print(match_phone.group()) # 默认整体匹配:010-12345667 print(match_phone.group(1)) # 010 print(match_phone.group(2)) # 12345667 # 引用分组 \1 msg = "abc" msg_match = re.match(r"<([0-9a-zA-Z]+)>(.+)$", msg) print(msg_match) # print(msg_match.groups()) # ('html', 'abc') print(msg_match.group(2)) # abc

你可能感兴趣的:(大数据,python,正则表达式)