正则表达式的理解

本文适合初学者,和没有系统学习正则表达式的人阅读,帮助您解决绝大部分正则表达式是的问题。
包括名词和量词的方法轻松理解的方法;获取匹配和非获取匹配的区别;匹配结果存储的方式;前缀后缀匹配;正则表达式中或和与操作等。

1 正则表达式主要两种类型

1.1 名词:代表是什么,用[]表示,如:[a]代表a字母,[ab]代表a或b字母,[0-9]代表0到9,还有一些简写形式,如:\w代表[a-zA-Z0-9_]字母数字或者下划线,\d代表[0-9]数字,\D代表\[^0-9\]非数字,\s代表[ \f\n\r\t\v]可见字符,.代表任意字符。

1.2 量词:代表个数,{n}代表有n个,{n,m}代表有n到m个,{n,}代表>=n个,{,m}代表<=m个,还有一些简写形式,如:*代表{0,}任意个,+代表{1,}至少有一个,?代表{0,1}代表最多有一个。

1.3 正则表达式翻译方法:[abc]{n,m} => 有n到m个'a'或'b'或'c',如果名词只有一个可以省略[],如果只需要一个可以省略量词。

import re

def printRes(res):
    if res:
        print(res.group())
    else:
        print("No match")

def main():
    str = "abc123123qwe"
    reg = re.compile(r"123")    # 一个(123)
    # search是匹配首个结果
    result = reg.search(str)
    printRes(result)            # 123

    reg = re.compile(r"123{2}") # 一个1一个2两个3
    # search是匹配首个结果
    result = reg.search(str)
    printRes(result)            # No match

    reg = re.compile(r"(123){2}")   # 两个(123)
    # search是匹配首个结果
    result = reg.search(str)
    printRes(result)            # 123123

    reg = re.compile(r"\d{2,3}[a-z]{1,2}")   #两到三个数字,一到两个小写字母
    # search是匹配首个结果
    result = reg.search(str)
    printRes(result)            # 123qw

if __name__ == '__main__':
    main()

正则表达式中|符号优先级最低。

python中 .代表非\n以外的任意字符,compile时加上re.DOTALL标签后才代表任意字符。

2 匹配结果:以python为例
import re

def main():
    str = "The cat is red and the dog is yellow"
    reg = re.compile(r"[t|T]he (cat|dog) is (\S+)") #\S 可见字符
    # search是匹配首个结果
    print(reg.search(str).group())  # 匹配的整个字符串 The cat is red
    print(reg.search(str).group(1)) # 字符串中第一个()的内容  cat
    print(reg.search(str).group(2)) # 字符串中第二个()的内容  red
    # findall是匹配所有的结果
    print(reg.findall(str)) # [('cat', 'red'), ('dog', 'yellow')]

    reg = re.compile(r"[t|T]he \S+ is \S+")
    # search是匹配首个结果
    print(reg.search(str).group())  # 匹配的整个字符串 The cat is red
    # findall是匹配所有的结果
    print(reg.findall(str)) # ['The cat is red', 'the dog is yellow']

    reg = re.compile(r"[t|T]he (?:cat|dog) is \S+")	# |的优先级最低
    # search是匹配首个结果
    print(reg.search(str).group())  # 匹配的整个字符串 The cat is red
    # findall是匹配所有的结果
    print(reg.findall(str))  # ['The cat is red', 'the dog is yellow']

if __name__ == '__main__':
    main()

()会单独放入到结果,而(?:)不会放入其中。

3 还有几种辅助类型

3.1 抽象位置:不占字符,只是显示位置,如:^表示开始,$表示结尾,\b表示单词边界(是\w\W的边界),\B非单词边界。

import re

def printRes(res):
    if res:
        print(res.group())
    else:
        print("No match")

def main():
    str = "this is windows7!"
    reg = re.compile(r'windows')    # 只要含有windows就可以匹配成功。
    # search是匹配首个结果
    result = reg.search(str)
    printRes(result)                # windows

    reg = re.compile(r'^windows$')  # w前必须是字符串开头,s后面必须是字符串结尾。
    # search是匹配首个结果
    result = reg.search(str)
    printRes(result)                # No match

    reg = re.compile(r'\bwindows\b')# w前面必须是\W,s后面必须是\W。
    # search是匹配首个结果
    result = reg.search(str)
    printRes(result)                # No match

if __name__ == '__main__':
    main()

注意:在正确性匹配时一定要加上^$符号,否则很容器出现漏洞。

3.2 非获取匹配: 只匹配内容,却不消耗字符,接下来还可以继续匹配。

import re

def printRes(res):
    if res:
        print(res.group())
    else:
        print("No match")

def main():
    str = "this is windows7!"

    reg = re.compile(r'windows(?=7)')   # 后缀
    # search是匹配首个结果
    result = reg.search(str)
    printRes(result)                    # windows

    reg = re.compile(r'windows(?=8)')   # 后缀
    # search是匹配首个结果
    result = reg.search(str)
    printRes(result)                    # No match

    reg = re.compile(r'windows(?!8)')   # 非后缀
    # search是匹配首个结果
    result = reg.search(str)
    printRes(result)                    # windows

    reg = re.compile(r'(?<=is )windows')# 前缀
    # search是匹配首个结果
    result = reg.search(str)
    printRes(result)                    # windows

    reg = re.compile(r'(?<=are )windows')# 前缀
    # search是匹配首个结果
    result = reg.search(str)
    printRes(result)                    # No match

    reg = re.compile(r'(?<!is )windows')# 非前缀
    # search是匹配首个结果
    result = reg.search(str)
    printRes(result)                    # No match

    # 接下来解释什么叫做非获取
    str = "989898"

    # 正常查找98的匹配结果
    reg = re.compile(r'98')
    # findall是匹配所有的结果
    print(reg.findall(str)) # ['98', '98', '98']

    # 匹配以98为前缀的98
    reg = re.compile(r'(?:98)(98)')
    # findall是匹配所有的结果
    print(reg.findall(str)) # ['98'] ?:需要获取(独占)字符串,下一次匹配无法使用。

    # 匹配以98为前缀的98
    reg = re.compile(r'(?<=98)(98)')
    # findall是匹配所有的结果
    print(reg.findall(str)) # ['98', '98'] 中间的98已经被第一次获取,但是非获取型匹配可以继续使用。

    # 正则表达式中有|操作符,但是没有&操作符。非获取型可以实现&
    # 下面实现字符串中,即有数字也有字母且不能是特殊字符的匹配。
    reg = re.compile(r'^(?=.*\d)(?=.*[a-zA-Z])\w*$')
    res = reg.search('123')
    printRes(res)           # No match
    res = reg.search('abc')
    printRes(res)           # No match
    res = reg.search('1bc')
    printRes(res)           # 1bc

if __name__ == '__main__':
    main()

4 两种模式:贪婪模式和非贪婪模式

贪婪模式尽量多匹配,非贪婪模式尽量少匹配。

import re

def printRes(res):
    if res:
        print(res.group())
    else:
        print("No match")

def main():
    str = "<h1 class='red'>Hello world!</h1>"
    # 默认是贪婪模式
    reg = re.compile(r'<h1.*>')
    # search是匹配首个结果
    result = reg.search(str)
    printRes(result)    # <h1 class='red'>Hello world!</h1>

    # 非贪婪模式
    reg = re.compile(r'<h1.*?>')
    # search是匹配首个结果
    result = reg.search(str)
    printRes(result)    # <h1 class='red'>

if __name__ == '__main__':
    main()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值