Python正则表达式

时间:2020-02-23 14:43:13  来源:igfitidea点击:

我们生活在一个信息时代,那里有大量数据,并且能够从数据中提取有意义的信息是成功的关键因素。
分析,数据挖掘和数据科学等领域致力于数据研究。
在本文中,我们将研究数据科学家工具箱中一个必不可少的,简单而强大的工具-正则表达式或者正则表达式。
我们将学习正则表达式以及如何在python脚本中使用它们来处理文本数据。

文本是数据的基本形式之一,人们使用文本进行交流和表达自己,例如在网页,教程 文章,文档,twitter/RSS feed等中。
其中正则表达式十分方便且功能强大。
无论是从网页过滤数据,数据分析还是文本挖掘–正则表达式都是完成这些任务的首选工具。
正则表达式使诸如(NLP)之类的文本处理任务更加简单,从而减少了编写手动脚本时必然发生的工作量,时间和错误。

在本文中,我们将了解什么是正则表达式以及如何在Python中使用它们。
接下来,我们将逐步介绍常用正则表达式的用法和应用。

到本文结尾,您将学习如何利用正则表达式的功能来自动执行日常文本处理任务。

什么是正则表达式?

正则表达式(RE或者regex)是描述文本模式的一系列字符。
使用正则表达式,我们可以为某些模式匹配输入数据(又名搜索),提取匹配的字符串(过滤,拆分),以及用替换替换出现的模式,所有这些都只需最少的代码。

大多数编程语言都内置支持对正则表达式进行定义和操作。
Perl,Python和Java是一些著名的编程语言,它们对正则表达式提供一流的支持。
此类编程语言中的标准库函数提供了正则表达式操作(搜索,过滤等)的高性能,健壮且(几乎)无错误的实现,从而可以轻松快速地生成可有效处理文本的高质量应用程序。

Python正则表达式入门

Python提供了一个名为re的内置模块来处理正则表达式。
要导入Python的re软件包,请使用:

import re

re包提供了一组使用正则表达式执行常见操作的方法。

在字符串中搜索模式

文本处理中最常见的任务之一是搜索字符串是否包含某种模式。
例如,您可能希望基于字符串包含数字的条件对字符串执行操作。
或者,您可能要通过确保密码包含数字和特殊字符来验证密码。
RE的" match"操作提供了此功能。

Python提供了两个基于正则表达式的原始操作:re.match()函数在字符串的开头检查模式匹配,而re.search()在字符串的任何地方检查模式匹配。
让我们看看如何使用这些功能:

re.match()函数

re.match()函数检查RE是否在字符串的开头匹配。
例如,用一些文本初始化变量" text",如下所示:

text = ['Charles Babbage is regarded as the father of computing.', 'Regular expressions are used in search engines.']

让我们写一个简单的正则表达式,它匹配一个包含以字母C开头的任何长度的字符串:

regex = r"C.*"

现在,我们不用担心上面的声明是如何解释的,并假设上面的语句创建了一个名为regex的变量,该变量与以C开头的字符串匹配。

我们可以测试文本中的字符串是否与正则表达式匹配,如下所示:

for line in text:
ans = re.match(regex, line)
type(ans)
if(ans):
  print(ans.group(0))

继续并运行该代码。
下面是运行此代码的python会话的屏幕截图。

正则表达式匹配搜索示例1

第一个字符串与此正则表达式匹配,因为它以字符" C"表示状态,而第二个字符串以字符" R"开头且与正则表达式不匹配。
如果找到匹配项,则match函数将返回_sre.SRE_Match对象,否则将返回None。

在python中,正则表达式被指定为原始字符串文字。
原始字符串文字的前缀为r,后跟引号的字符串文字。
与普通字符串文字不同,Python不会在原始字符串文字中解释特殊字符,例如'''。
这是重要且必要的,因为特殊字符在正则表达式语法中的含义与在标准python字符串文字中的含义不同。
稍后再详细介绍。

找到匹配项后,我们可以在返回的match对象上使用group()方法获取与模式匹配的字符串部分。
我们可以通过传递0作为参数来获取整个匹配字符串。

ans.group(0)

示例输出:

Charles Babbage is regarded as the father of computing.

正则表达式的构建基块

在本节中,我们将研究组成正则表达式的元素以及正则表达式的构建方式。
正则表达式包含组,每个组包含各种说明符,例如字符类,中继器,标识符等。
说明符是与特定类型的模式匹配的字符串,并具有用于描述所需模式的自己的格式。
让我们看一下常见的说明符:

身份标识

标识符与字符的子集匹配,例如小写字母,数字,空白等。
正则表达式提供了方便的标识符列表,以匹配不同的子集。
一些常用的标识符是:

  • \ d =匹配字符串中的数字(数字字符)

  • \ D =匹配除数字以外的任何内容

  • \ s =匹配空白(例如空格,TAB等)。

  • \ S =匹配空格以外的任何内容

  • \ w =匹配字母/字母和数字

  • \ W =匹配字母以外的任何内容

  • \ b =匹配可以分隔单词的任何字符(例如,空格,连字符,冒号等)。

  • . =匹配任何字符,除了换行符。
    因此,它被称为通配符。
    因此,".*"将匹配任何字符,任何时间。

注意:在上面的regex示例和本节中的所有其他示例中,为了可读性,我们省略了regex字符串文本的前导 r。在python代码中使用时,这里给出的任何文本都应该声明为原始字符串文本。

重复器

重复器用于指定一个或者多个组的出现。
以下是一些常用的中继器。

*符号

星号运算符表示前一个元素的0个或者多个重复,并尽可能多。
" ab *"将匹配" a"," ab"," abb"或者" a",后跟任意多个b。

" +"符号

加号运算符表示前一个元素的1个或者多个重复,并尽可能多。
" ab +"将匹配" a"," ab"," abb"或者" a",然后至少出现1次" b";它与" a"不匹配。

"?"符号

该符号表示前面的元素最多出现一次,即它可能存在也可能不存在于要匹配的字符串中。
例如," ab +"将匹配" a"和" ab"。

{n}花括号

花括号将前一个元素指定为精确匹配n次。
b {4}将精确匹配四个" b"字符,但不超过/少于4个。

符号*,+ 、?和{}被称为重复器,因为它们指定重复前一个元素的次数。

其他说明符

[]大括号

方括号匹配其中包含的任何单个字符。
例如,[aeiou]将匹配任何小写的元音,而[a-z]将匹配a-z中的任何字符(区分大小写)。
这也称为字符类。

|

竖线用于分隔其他选项。
photo | foto匹配" photo"或者" foto"。

^符号

插入符号在字符串的开头指定匹配的位置,但在方括号内使用时除外。
例如," ^ I"将匹配以" I"开头的字符串,但不会匹配以" I"开头的字符串。
这基本上与re.match和vs.search提供的功能相同。

当用作字符类中的第一个字符时,它将反转字符类的匹配字符集。
例如," [^ aeiou]"将匹配a,e,i,o或者u以外的任何字符。

$符号

美元符号指定字符串末尾的匹配位置。

()

括号用于对RE的不同符号进行分组,以充当单个块。
([a-z] \ d +)将匹配包含a-z,后跟任意数字的模式。
整个匹配项被视为一个组,可以从字符串中提取出来。
稍后再详细介绍。

Python正则表达式的典型用例

现在,我们讨论了编写RE的基础。
让我们动手做正则表达式编写。

re.match()函数

使用match函数可以匹配大写和小写字母。

ans = re.match(r"[a-zA-Z]+", str)
print(ans.group(0))

上面的正则表达式与字符串中找到的第一个单词匹配。
" +"运算符指定字符串应至少包含一个字符。

示例输出:

The

如您所见,正则表达式与字符串中找到的第一个单词匹配。
" The"一词之后有一个空格,该空格不视为字母。
因此,匹配将停止,并且该函数仅返回找到的第一个匹配项。
假设字符串以数字开头。
在这种情况下,尽管字符串在数字后有字母,但match()函数将返回空值。
例如,

str = "1837 was the year when Charles Babbage invented the Analytical Engine"
ans = re.match(r"[a-zA-Z]+", str)
type(ans)

上面的正则表达式返回null,因为match函数仅返回字符串中的第一个元素。
尽管该字符串包含字母,但它前面还有一个数字。
因此,match()函数返回null。
使用search()函数可以避免这个问题。

re.search()函数

search()函数匹配字符串中的指定模式,类似于match()函数。
区别在于," search()"函数全局匹配模式,与仅匹配字符串的第一个元素不同。
让我们使用" search()"函数尝试相同的示例。

str =  "1837 was the year when Charles Babbage invented the Analytical Engine"
ans = re.search(r"[a-zA-Z]+", str)
type(ans)

示例输出:

was

这是因为" search()"函数返回一个匹配项,尽管该字符串不是以字母开头,而是在字符串的其他位置找到了。

从头到尾匹配字符串

我们可以使用正则表达式使用尖号运算符^来查找字符串是否以特定的模式开头。
类似地,如果字符串以给定的模式结尾,则使用$操作符$进行匹配。
让我们写一个正则表达式来了解这一点:

str =  "1937 was the year when Charles Babbage invented the Analytical Engine"
if re.search(r"^1837", str):
  print("The string starts with a number")
else:
  print("The string does not start with a number")
type(ans)

示例输出:

The string starts with a number

re.sub()函数

我们已经探索过使用正则表达式在字符串中查找模式。
让我们继续寻找如何在字符串中替换文本。
为此,我们使用sub()函数。
sub()函数在字符串中搜索特定的模式,并将其替换为新的模式。

str = "Analytical Engine was invented in the year 1837"
ans = re.sub(r"Analytical Engine", "Electric Telegraph", str)
print(ans)

如您所见,sub()函数的第一个参数是正则表达式,用于搜索要替换的模式。
第二个参数包含您希望替换旧文本的新文本。
第三个参数是在其上执行" sub"操作的字符串。

示例输出:

Electric Telegraph was invented in the year 1837

用标识符编写正则表达式

让我们通过一个示例来了解如何使用包含标识符的正则表达式。
要删除字符串中的数字,我们使用以下正则表达式:

str = "Charles Babbage invented the Analytical Engine in the year 1937"
ans = re.sub(r"\d", "", str)
print(ans)

上面的脚本使用标识符" \ d"查找字符串中的数字,并将其替换为空字符串。

示例输出:

Charles Babbage invented the Analytical Engine in the year

分割字符串

re包提供了split()函数来分割字符串。
此函数返回拆分令牌的列表。
例如,下面的" split"函数在发现逗号时会拆分字符串:

str = "Charles Babbage was considered to be the father of computing, after his invention of the Analytical Engine, in 1837"
ans = re.split(r"\,", str)
print(ans)

示例输出:

['Charles Babbage was considered to be the father of computing', 'after his invention of the Analytical Engine', 'in 1837']

re.findall()函数

" findall()"函数返回一个列表,该列表包含字符串中所有匹配的发音。

让我们编写一个脚本,从实现findall()函数的电子邮件ID列表中查找域类型:

result=re.findall(r'@\w+.\w+','[email protected], [email protected], [email protected])
print result

示例输出:

['@gmail.com', '@yahoo.in', '@samskitchen.com']