Python中的正则表达式


2021年8月23日, Learn eTutorial
1817

在本教程中,您将学习什么是正则表达式,它在编程中有多大用处,以及如何通过一些简单的示例和图表来实现模式匹配。此外,您还将学习导入're'模块,该模块包含一些有用的函数,如match、search、findall等。

在讨论正则表达式之前,让我们考虑一下我们在日常生活中有意或无意使用的特定功能,即使用“查找”搜索字符串,使用“查找和替换”在文字处理器和文本编辑器中查找和替换字符串,以及验证电子邮件和密码等输入。这些是如何发生的?答案就在本教程中。

什么是正则表达式?

正则表达式是定义某种搜索模式的字符序列。在编程环境中,正则表达式起着至关重要的作用,因为它为字符序列定义了搜索模式。正则表达式的缩写是Regex。

例如,

a*b = {b,ab, aab,aaab,aaaab,.......}

ab* = { a,ab, abb, abbb, abbbb,.....}
 

这里,a*b和ab*是语言{a,b}的正则表达式,*表示零次或多次。

Python中的re模块

现在,让我们开始学习Python中正则表达式的实现,从哪里开始,以及如何开始。在Python中,用于正则表达式的函数和方法都包含在一个名为re的模块中。因此,要执行任何Regex功能,必须导入re模块。下面显示了导入re模块的原型。

import re 

元字符

特殊字符(称为元字符)的运用增强了正则表达式的功能。在正则表达式中,元字符是对计算机程序具有特殊含义的字符。方括号([])、插入符号(^)、美元符号($)、句点(.)、竖线(|)、星号(*)、加号(+)、问号(?)、花括号({})、括号(())、反斜杠(\)等都是Regex中使用的一些元字符。

根据操作,元字符可分为以下几类:

Metacharacters

元字符

字符类的元字符

  1. [] - 方括号

    方括号是正则表达式中的一个元字符,用于定义字符集。换句话说,方括号内的字符构成字符集,并尝试匹配方括号内的任何单个字符。

    示例

    Example of Square brackets

    方括号示例

    为了更好地理解,正则表达式可以可视化为:

    regular expression can be visualised
    1. 用于字符集范围的方括号

      使用方括号[],我们还可以表示字符范围。“-”(连字符)用于表示字符范围。例如:

      Example of Square brackets

      在此示例中:

      [a-d]是与[abcd]等效的正则表达式。

      [0-4]也是与[01234]等效的正则表达式。

      • [a-z] - 表示所有字母(a到z)都可以在regex中使用。
      • [0-9] - 表示所有从0到9的数字都可以在regex中使用。
    2. 字符集范围的否定

      还可以反转字符集范围。这可以通过将插入符号(^)紧跟在方括号的开括号后面来完成。这可以视为:

      • [^aeiou]:这将得到除元音字母外的所有字母。
      • [^0-5]:匹配除0、1、2、3、4和5之外的所有数字。
  2. .- 句点

    句点或圆点充当通配符,匹配除换行符外的任何单个字符。句点的数量表示可以包含的字符数量。

    Example of Period symbol

    句点符号示例

  3. ^ - 插入符号

    元字符^(插入符号)通常前缀一个字符,表示正则表达式以该特定字符开头。

    Example of ^(caret symbol)

    插入符号(^)示例

  4.  $ - 美元符号

    元字符$(美元符号)通常后缀一个字符,表示正则表达式以该特定字符结尾。

    Hierarchical structure of the package

    美元符号($)示例

量词元字符

正则表达式中的量词表示字符、元字符或字符集的出现次数。*,+,?和{}属于量词。

  1. * - 星号

    星号(*)表示字符串中模式的零次或多次出现

    Example of Asterisk

    星号示例

  2. + - 加号

    加号(+)表示字符串中模式的一次或多次出现

    (+)/

    加号(+)示例

  3. ? - 问号

    问号(?)表示字符串中模式的零次或一次出现

    Example of question mark(?)

    问号(?)示例

  4. {} - 花括号

    花括号也属于量词类别,用于表示某些字符、元字符或字符集的重复。花括号可以采取以下形式:

    {n} 前面的字符精确地重复n次。
    {n,} 前面的字符至少重复n次。
    { ,m} 前面的字符最多重复m次。
    {n,m} 前面的字符重复n到m次(包括n和m)。
    Example of Curly braces

    花括号示例

布尔元字符

  1. | - 交替

    交替通常用于通过表示“此或彼”来实现逻辑OR操作。这可以通过竖线符号(|)来实现,它匹配一个正则表达式与任何可能的正则表达式。

    形式为<regex-1>|<regex-2>|....|<regex-n>的正则表达式最多匹配<regex-i>中的一个。

    Hierarchical structure of the package

    交替示例

分组结构

  1. 括号()

    分组结构将正则表达式分割成小的子表达式组。分组可以通过括号(())符号来完成。

    Example of parenthesis (

    括号(())示例

分组的应用包括:

  1. 可以轻松地将量词应用于子表达式或组。
    Regex 解释 示例/匹配
    (Hi)+ +应用于整个字符集 Hi HiHi HiHiHi
    Hi+ +仅应用于字符“i” Hi Hii Hiiii
  2. 允许将交替限制在正则表达式的一部分
    Regex 解释 示例/匹配
    This is a car|bus |应用于'This is a car'和'bus' This is a car bus
    This is a (car|bus) |应用于'This is a car'和'This is a bus' This is a car This is a bus
  3. 允许捕获由组匹配的搜索字符串部分

    借助分组结构,我们还可以提取匹配子表达式或子模式的字符串片段。与组结构相关的捕获字符串的两种方法是group()和groups(),您将在本教程后面学习。

转义元字符

  1. \ - 反斜杠

    正则表达式中的反斜杠(\)用于转义特殊字符,包括元字符。通过在元字符前放置反斜杠,可以移除元字符的特殊含义,并将其指定为字面字符本身。例如,可以通过在其前面放置(\)字符来将元字符(?)问号视为字面字符。

    此外,当您不确定某些字符的含义时,反斜杠也很有用,可以通过在字符前放置反斜杠来验证。

特殊序列

在正则表达式中,特殊序列是前缀为反斜杠的字符序列。下面列出了特殊序列及其含义和示例,以便于理解:

Special sequences

正则表达式函数

现在您已经很好地了解了正则表达式中使用的元字符和特殊字符。本节将教您如何使用一些常见且常用的正则表达式函数来实现它们。下面列出了与re模块相关的流行函数。

  1. Match() - 成功时返回匹配对象,失败时返回None。
  2. Search() - 如果找到匹配项,则返回匹配对象,否则返回None。
  3. Findall() - 返回包含所有匹配项的列表。
  4. Split() - 返回分割发生处的字符串列表。
  5. Sub() - 替换一个或多个匹配项。

下面将对每个函数进行详细解释,并附有简单易懂的示例。

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

检查下面使用match()函数验证电子邮件格式的代码。

import re

string = '[email protected]'

pattern = '^[a-zA-Z0-9+_.-]+@[a-zA-Z0-9.-]+$'

result = re.match(pattern, string)

if result:
  print("Valid email format")
else:
  print("Invalid email format") 

输出

Valid email format

在此示例中,我们使用match函数检查模式是否与提供的字符串匹配。在这里,我们使用正则表达式验证电子邮件格式,如果测试字符串不符合模式,则会输出“无效的电子邮件格式”。

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

re模块用于操作正则表达式的另一个方法是search()方法,它接受两个参数——模式和字符串。顾名思义,此方法搜索模式与字符串匹配的初始位置。如果找到完美匹配,则re.search()将返回一个匹配对象,否则将产生None作为结果。以下是示例:

import re

string = 'Python is a universal programming language developed by a Dutch Programmer called Guido Van Rossum in 1989 and released in 1991'

pattern ='\d'

result = re.search(pattern, string)

if result:
  print("search successful")
else:
  print("search unsuccessful") 

输出

search successful

在这里,结果包含一个匹配对象。

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

此方法沿从左到右方向扫描字符串,并按找到的顺序返回所有匹配项的列表。

import re

string = 'Python is a universal programming language developed by a Dutch Programmer called Guido Van Rossum in 1989 and released in 1991'

pattern ='(\d+)'

result = re.findall(pattern, string)

if result:
  print(result)
else:
  print("search unsuccessful") 

输出

['1989', '1991']

如果未找到匹配项,则结果将是一个空列表。

re.split(pattern, string, maxsplit=0, flags=0)

此方法与我们之前学到的方法略有不同。在此方法中,字符串将根据模式匹配进行分割,结果将是一个包含分割发生处的字符串列表。观察以下示例:

string = 'Python is a universal programming language developed by a Dutch Programmer called Guido Van Rossum in 1989 and released in 1991.'
pattern = '\d+'

result = re.split(pattern, string) 
print(result) 

输出

['Python is a universal programming language developed by a Dutch Programmer called Guido Van Rossum in ', ' and released in ', '.']

在上面的代码片段中,字符串在遇到数字时会进行分割。当找不到匹配项时,split()方法将返回一个包含原始字符串的列表。split方法的另一个特点是可以通过为参数maxsplit指定一个值来限制分割次数。

import re

string = 'Python is a universal programming language developed by a Dutch Programmer called Guido Van Rossum in 1989 and released in 1991.'
pattern = '\d+'

result = re.split(pattern, string,1) 
print(result) 

输出

['Python is a universal programming language developed by a Dutch Programmer called Guido Van Rossum in ', ' and released in 1991.']

注意:默认情况下,maxsplit的值为零(所有可能的分割)。

re.sub(pattern, repl, string, count=0, flags=0)

此方法将匹配项替换为所需的字符串。

import re

string = 'abc 123 def 456 ghi 789'
pattern = '[a-z]'
replace = '0'

result = re.sub(pattern,replace,string) 
print(result) 

输出

000 123 000 456 000 789

与split()一样,您可以通过将可选参数count设置为一个值来限制替换次数。默认情况下,count的值为零,这意味着将执行所有可能的替换。

import re

string = 'abc 123 def 456 ghi 789'
pattern = '[a-z]'
replace = '0'

result = re.sub(pattern,replace,string,4) 
print(result) 

输出

000 123 0ef 456 ghi 789

在上述方法中,您已经看到了一个可选参数flags,它是用于控制匹配各个方面的修饰符。默认情况下,flags的值为零。

匹配对象

正则表达式中的匹配对象是包含搜索和结果信息的对象。匹配对象始终包含真值(True或False)。如果没有匹配项,则返回None而不是匹配对象。观察以下代码的输出:

import re

string = 'I am 18 years old.'
pattern = '\d+'

result = re.search(pattern, string) 
print(result)
 

输出

span=(5, 7), match='18'

匹配对象具有以下属性和方法来获取搜索和结果的信息:

span():返回一个包含匹配项的开始和结束索引的元组。

group():返回与模式匹配的字符串部分。

String:返回传入的字符串。


import re

string = 'I am 18 years old.'
pattern = '\d+'

result = re.search(pattern, string) 
print(result.span())
print(result.group())
print(result.string)

 

输出


(5, 7)
18
I am 18 years old.

要了解有关匹配对象属性和方法的更多信息,请访问Python的文档页面。