Python模块-re

正则表达式本身是一种小型的、高度专业化的编程语言。Python 的 re 模块(Regular Expression 正则表达式)提供各种正则表达式的匹配操作,Python 会将正则表达式转化为字节码,利用 C 语言的匹配引擎进行深度优先的匹配。

参考:
https://www.cnblogs.com/tina-python/p/5508402.html
https://blog.csdn.net/sinat_20791575/article/details/54139404
https://www.cnblogs.com/dreamer-fish/p/5282679.html

re模块中常用功能函数

compile()

re.compile(pattern, flags=0)
编译正则表达式,返回一个 pattern 对象
pattern: 编译时用的表达式字符串
flags: 编译标志位,用于修改正则表达式的匹配方式,如:是否区分大小写,多行匹配等。常用的flags有:

标志 含义
re.S(DOTALL) 使.匹配包括换行在内的所有字符
re.I(GNORECASE) 使匹配对大小写不敏感
re.L(LOCALE) 做本地化识别(locale-aware)匹配,法语等
re.M(MULTILINE) 多行匹配,影响^和$
re.X(VERBOSE) 该标志通过给予更灵活的格式以便将正则表达式写得更易于理解
re.U 根据Unicode字符集解析字符,这个标志影响\w,\W,\b,\B
prog = re.compile(pattern)
result01 = prog.match(string)
result02 = prog.search(string)
result03 = prog.findall(string)

# 等价于
result = re.match(pattern, string)

match()

re.match(pattern, string, flags=0)
如果字符串的开头能匹配正则表达式,返回对应的 match 对象,否则返回None

re.search(pattern, string, flags=0)
在字符串中查找,是否能匹配正则表达式,若是,返回对应的 match 对象,否则返回None

phoneMatch = re.search(r"(\d\d\d)-(\d\d\d)-(\d\d\d\d)", 
                        "My number is 111-222-3333")
 
print(phoneMatch.group())
>>>'111-222-3333'
print(phoneMatch.groups())
>>>('111', '222', '3333')
 
print(phoneMatch.group(0))
>>>'111-222-3333'
print(phoneMatch.group(1))
>>>'111'
print(phoneMatch.group(2))
>>>'222'
print(phoneMatch.group(3))
>>>'3333'

findall()

re.findall(pattern, string, flags=0)
找到 RE 匹配的所有子串,并把它们作为一个列表返回。如果无匹配,返回空列表

re.findall(r"(\d\d\d)-(\d\d\d)-(\d\d\d\d)",
          "My number is 111-222-3333; Your number is 123-555-8899")
>>>['111','222','333']

re.subn(r"n(.*?)er", "aa", "My number is 111-222-3333; Your number is 123-555-8899")
>>>('My aa is 111-222-3333; Your aa is 123-555-8899', 2)

re.findall(r"n.*?er", "My number is 111-222-3333; Your number is 123-555-8899")
>>>['number', 'number']

finditer()

re.finditer(pattern, string, flags=0)
找到 RE 匹配的所有子串,并把它们作为一个迭代器返回(没啥用)

split()

re.split(pattern, string, maxsplit=0, flags=0)
使用正则表达式分离字符串。如果用括号将正则表达式括起来,那么匹配的字符串也会被列入到list中返回。maxsplit是分离的次数,maxsplit=1分离一次,默认为0,不限制次数

text = "JGood is a handsome boy, he is cool, clever, and so on..."
re.sub(r'\s+', '-', text)

>>>'JGood-is-a-handsome-boy,-he-is-cool,-clever,-and-so-on...'

sub()

re.sub(pattern, repl, string, count=0, flags=0)
找到 RE 匹配的所有子串,并将其用一个不同的字符串替换。可选参数 count 是模式匹配后替换的最大次数;count 必须是非负整数。缺省值是 0 表示替换所有的匹配。如果无匹配,字符串将会无改变地返回

subn()

subn(pattern, repl, string, count=0, flags=0)
返回元组,结果和替换次数

使用总结

  • 日常使用search和findall

  • compile基本不用使用

  • match与search与findall的区别

    re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;而re.search匹配整个字符串,直到找到一个匹配

    re.match('[\d]',"abc33")
    >>>None
    re.search('[\d]',"abc33").group()
    >>>3
    re.findall('[\d]',"abc33")
    >>>['3', '3']
    

正则表达式符号

  • 点号"."

    • 点号可以代表任意除\n以外的字符
    • 一个点号代表一个字符,相当于占位符
    • chenjunpeng -> chenjun...g
  • 星号"*"

    • 星号代表它前面的子表达式0次到多次
    • chenjunpeng -> chen.*g
    • chennnnnnn -> chen*
    • chen -> che*
  • 问号"?"

    • 问好代表它前面的子表达式0次或者1次
    • chenjunpeng -> Chinju.?peng
    • chenjunpeng -> chenu?junpeng
  • 加号"+"

    • 加号代表它前面的子表达式1次或者多次
    • Batwoman ->Bat(wo)+man
  • 花括号{}

    • {2,5}?
    • 匹配制定次数
    • Batwowowoman ->Bat(wo){2,5}man
  • 管道符"|"

  • 括号()

    • 只要括号里面的内容
    • 括号内容相当一个完整的子表达式
  • 转义字符" \ "

    • 反斜杠不能单独使用
    • 让特殊字符变为普通字符:"\*"
    • 让普通字符变为特殊字符:"\d" 代表数字
  • 启始"^"

  • 结尾"$"

  • 提取数字

    • \d
    • 正则表达式里面,使用 “\d” 来表示一位数字。这里要强调一下,\d 虽然是由从左上向右下的斜杠和字母d构成的,但是我们要把\d看成是一个正则表达式符号整体。从左上向右下的斜杠,名字叫做“反斜杠”,在正则表达式中是作为转义字符,不能单独使用。
    • 如果要提取两个数字,我们可以使用 \d\d,如果要提取三个数字,我们可以使用\d\d\d,但是问题来了,如果我们不知道有这个数有多少位怎么办呢?就需要使用上一课讲到的 + 号。+ 号可以匹配它前面的符号一次或者多次。所以使用 \d+,可以表示一个任意位数的数字。
  • 提取文本

    • .* 贪心算法

    • .*? 非贪心算法

    • 对于文本来说,我们在爬虫中一般使用 .*? 这三个符号来完成。

    • 我们知道点号表示任意非换行符的字符,*号表示匹配它前面的字符零次或者任意多次。所以 .* 表示匹配一串任意长度的字符串任意次。这个时候必须在 .* 的前后加其他的符号来限定范围,否则得到的结果就是原来的整个字符串。

    • 如果在 .* 的后面加一个问号变成 .*? ,那么可以得到什么样的结果呢?问号表示匹配它前面的符号0次或者1次。于是 .*? 的意思就是,匹配一个能满足要求的最短字符串

    • 换行符\n隔断处理

  • 字符类

    实例 描述
    [Pp]ython 匹配 "Python" 或 "python"
    rub[ye] 匹配 "ruby" 或 "rube"
    [aeiou] 匹配中括号内的任意一个字母
    [0-9] 匹配任何数字。类似于 [0123456789]
    [a-z] 匹配任何小写字母
    [A-Z] 匹配任何大写字母
    [a-zA-Z0-9] 匹配任何字母及数字
    [^aeiou] 除了aeiou字母以外的所有字符
    [^0-9] 匹配除了数字外的字符
  • 特殊字符类

    实例 描述
    . 匹配除 "\n" 之外的任何单个字符。要匹配包括 '\n' 在内的任何字符,请使用象 '[.\n]' 的模式。
    \d 匹配一个数字字符。等价于 [0-9]。
    \D 匹配一个非数字字符。等价于 [^0-9]。
    \s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。
    \S 匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。
    \w 匹配包括下划线的任何单词字符。等价于'[A-Za-z0-9_]'。
    \W 匹配任何非单词字符。等价于 '[^A-Za-z0-9_]'。

贪心和非贪心匹配

Python的正则表达式匹配模式默认是贪心匹配

问号模式是非贪心模式

# 贪心
re.search(r"\d{2,5}", r"123456").group()
>>> '12345'

# 非贪心
re.search(r"\d{2,5}?", r"12346").group()
>>> '12'
# 贪心
re.findall(r"n(.*)er", "My number is 111-222-3333; Your number is 123-555-8899")
>>>['umber is 111-222-3333; Your numb']

# 非贪心
re.findall(r"n(.*?)er", "My number is 111-222-3333; Your number is 123-555-8899")
>>>['umb', 'umb']
posted @ 2019-03-05 15:07  stream886  阅读(310)  评论(0编辑  收藏  举报