美文网首页
正则表达式

正则表达式

作者: 大象信步走来 | 来源:发表于2020-07-02 22:48 被阅读0次

    正则表达式(称为RE,或正则,或正则表达式模式)本质上是嵌入在Python中的一种微小的、高度专业化的编程语言,可通过 re 模块获得。

    简单模式

    正则表达式用于对字符串进行操作,因此我们将从最常见的任务开始:匹配字符

    匹配字符:匹配不同的字符集合是正则表达式可以做的第一件事

    元字符是 []

    [abc],[a-c],[0-9],[abc] \作为元字符在中括号内失效,[^5] 匹配非'5'的字符,[5^] 将匹配 '5''^'

    元字符是反斜杠,\

    反斜杠来移除它们的特殊含义:\[\\

    '\' 开头的特殊序列表示通常有用的预定义字符集

    • \d

      匹配任何十进制数字;这等价于类 [0-9]

    • \D

      匹配任何非数字字符;这等价于类 [^0-9]

    • \s

      匹配任何空白字符;这等价于类 [ \t\n\r\f\v]转义符在中括号中不失效吗

    • \S

      匹配任何非空白字符;这相当于类 [^ \t\n\r\f\v]

    • \w

      匹配任何字母与数字字符;这相当于类 [a-zA-Z0-9_]

    • \W

      匹配任何非字母与数字字符;这相当于类 [^a-zA-Z0-9_]

    元字符是 .

    它匹配除换行符之外的任何内容,并且有一个可选模式( re.DOTALL )甚至可以匹配换行符

    重复:指定正则的某些部分必须重复一定次数

    元字符是 *

    一个逐步的例子将使这更加明显。 让我们考虑表达式 a[bcd]*b。 这个正则匹配字母 'a',类 [bcd] 中的零或多个字母,最后以 'b' 结尾。 现在想象一下这个正则与字符串 'abcbd' 匹配。

    步骤 匹配 说明
    1 a 正则中的 a 匹配。
    2 abcbd 引擎尽可能多地匹配 [bcd]* ,直到字符串结束。
    3 失败 引擎尝试匹配 b ,但是当前位置位于字符串结束,所以匹配失败。
    4 abcb 回退一次,[bcd]* 少匹配一个字符。
    5 失败 再次尝试匹配 b , 但是当前位置是最后一个字符 'd'
    6 abc 再次回退,所以 [bcd]* 只匹配 bc
    6 abcb 再试一次 b 。 这次当前位置的字符是 'b' ,所以它成功了。

    元字符是 +

    ca+t 将匹配 'cat' (1 个 'a'),'caaat' (3 个 'a'),但不会匹配 'ct'

    重复限定符。 问号字符 ? 匹配一次或零次

    home-?brew 匹配 'homebrew''home-brew'

    重复限定符是 {m,n}

    a/{1,3}b 将匹配 'a/b''a//b''a///b' 。 它不匹配没有斜线的 'ab',或者有四个的 'a////b', {0,}* 相同, {1,} 相当于 +{0,1}? 相同。 最好使用 *+? ,只要因为它们更短更容易阅读。

    使用正则表达式

    re 模块提供了正则表达式引擎的接口,允许你将正则编译为对象,然后用它们进行匹配

    编译正则表达式

    正则表达式被编译成模式对象,模式对象具有各种操作的方法,例如搜索模式匹配或执行字符串替换

    p = re.compile('ab*')

    re.compile() 也接受一个可选的 flags 参数,用于启用各种特殊功能和语法变体, p = re.compile('ab*', re.IGNORECASE)

    正则作为字符串传递给 re.compile() ,将正则放在字符串中可以使 Python 语言更简单,但有一个缺点:反斜杠灾难。解决方案 r"\n" 是一个包含 '\''n' 的双字符字符串,而 "\n" 是一个包含换行符的单字符字符串。

    应用匹配

    一旦你有一个表示编译正则表达式的对象,你用它做什么? 模式对象有几种方法和属性。

    方法 / 属性 目的
    match() 确定正则是否从字符串的开头匹配。
    search() 扫描字符串,查找此正则匹配的任何位置。
    findall() 找到正则匹配的所有子字符串,并将它们作为列表返回。
    finditer() 找到正则匹配的所有子字符串,并将它们返回为一个 iterator
    >>> import re
    >>> p = re.compile('[a-z]+')
    >>> p
    re.compile('[a-z]+')
    
    >>> p.match("")
    >>> print(p.match(""))
    None
    
    >>> m = p.match('tempo')
    >>> m
    <re.Match object; span=(0, 5), match='tempo'>
    

    现在你可以检查 匹配对象 以获取有关匹配字符串的信息。 匹配对象实例也有几个方法和属性;最重要的是:

    方法 / 属性 目的
    group() 返回正则匹配的字符串
    start() 返回匹配的开始位置
    end() 返回匹配的结束位置
    span() 返回包含匹配 (start, end) 位置的元组

    尝试这些方法很快就会清楚它们的含义:

    group() 返回正则匹配的子字符串。 start()end() 返回匹配的起始和结束索引。 span() 在单个元组中返回开始和结束索引。 由于 match() 方法只检查正则是否在字符串的开头匹配,所以 start() 将始终为零。 但是,模式的 search() 方法会扫描字符串,因此在这种情况下匹配可能不会从零开始。:

    >>>

    >>> print(p.match('::: message'))
    None
    >>> m = p.search('::: message'); print(m)
    <re.Match object; span=(4, 11), match='message'>
    >>> m.group()
    'message'
    >>> m.span()
    (4, 11)
    

    在实际程序中,最常见的样式是在变量中存储 匹配对象,然后检查它是否为 None。 这通常看起来像:

    p = re.compile( ... )
    m = p.match( 'string goes here' )
    if m:
        print('Match found: ', m.group())
    else:
        print('No match')
    

    两种模式方法返回模式的所有匹配项。 findall() 返回匹配字符串的列表:

    >>>

    >>> p = re.compile(r'\d+')
    >>> p.findall('12 drummers drumming, 11 pipers piping, 10 lords a-leaping')
    ['12', '11', '10']
    

    在这个例子中需要 r 前缀,使字面为原始字符串字面,因为普通的“加工”字符串字面中的转义序列不能被 Python 识别为正则表达式,导致 DeprecationWarning 并最终产生 SyntaxError。 请参阅 反斜杠灾难

    findall() 必须先创建整个列表才能返回结果。 finditer() 方法将一个 匹配对象 的序列返回为一个 iterator

    >>>

    >>> iterator = p.finditer('12 drummers drumming, 11 ... 10 ...')
    >>> iterator  
    <callable_iterator object at 0x...>
    >>> for match in iterator:
    ...     print(match.span())
    ...
    (0, 2)
    (22, 24)
    (29, 31)
    

    模块级别函

    >>> print(re.match(r'From\s+', 'Fromage amk'))
    None
    >>> re.match(r'From\s+', 'From amk Thu May 14 19:12:10 1998')  
    <re.Match object; span=(0, 5), match='From '>
    

    编译标志

    这是一个可用标志表,以及每个标志的更详细说明。

    Flag 含义
    ASCII, A 使几个转义如 \w\b\s\d 匹配仅与具有相应特征属性的 ASCII 字符匹配。
    DOTALL, S 使 . 匹配任何字符,包括换行符。
    IGNORECASE, I 进行大小写不敏感匹配。
    LOCALE, L 进行区域设置感知匹配。
    MULTILINE, M 多行匹配,影响 ^$
    VERBOSE, X (为 '扩展') 启用详细的正则,可以更清晰,更容易理解。

    re.I | re.M 设置 IM 标志

    这里的正则使用 re.VERBOSE;看看阅读有多容易?: charref = re.compile(r""" &[#] # Start of a numeric entity reference ( 0[0-7]+ # Octal form | [0-9]+ # Decimal form | x[0-9a-fA-F]+ # Hexadecimal form ) ; # Trailing semicolon """, re.VERBOSE) 如果没有详细设置,正则将如下所示: charref = re.compile("&#(0[0-7]+" "|[0-9]+" "|x[0-9a-fA-F]+);")

    更多元字符

    Crow|Servo 将匹配 'Crow''Servo',而不是 'Cro''w''S''ervo'

    print(re.search('^From', 'From Here to Eternity')) <re.Match object; span=(0, 4), match='From'> print(re.search('^From', 'Reciting From Memory')) None `

    print(re.search('}$', '{block}')) <re.Match object; span=(6, 7), match='}'> >>> print(re.search('}$', '{block} ')) None >>> print(re.search('}$', '{block}\n')) <re.Match object; span=(6, 7), match='}'> `

    相关文章

      网友评论

          本文标题:正则表达式

          本文链接:https://www.haomeiwen.com/subject/ufgdqktx.html