大家好,我是Mr数据杨,一个对数据和编程充满热情的人。今天,我要和大家分享关于正则表达式的一些知识。你可能会问,正则表达式是什么?我们日常生活中怎么会用到这个复杂又晦涩的概念呢?

让我举个例子,你是否有过在长长的购物清单中查找某种商品,或者在一大堆邮箱里找出所有的订阅邮件的经历?这其实和我们今天要谈的主题有异曲同工之妙。在编程中,我们经常需要在大量的文字中找出我们关注的信息,或者替换某些特定的字符。这就是正则表达式的强大之处。

我们将会探讨正则表达式的搜索功能,它可以帮我们在海量的数据中找出我们需要的信息。接下来,我们会讲述正则表达式的替换函数,它可以帮我们将特定的文字替换为我们想要的内容。最后,我们会深入到正则表达式的实用功能,看看如何利用它来简化我们的日常编程工作。

好了,让我们一起启程,探索正则表达式的奇妙世界吧!

1951 年,数学家 Stephen Cole Kleene 描述了正则语言的概念,它是一种可以被有限自动机识别并可以使用正则表达式形式表达的语言。在 1960 年代中期,计算机科学先驱 Ken Thompson 是 Unix 的原始设计者之一,他使用 Kleene 的符号在 QED 文本编辑器中实现了模式匹配。

对于新手来说正则表达式其实很头疼的,竟让让你怀疑认证怎么能发明出来这么奇怪的东西,其实正则表达式是一个特殊的字符序列,它定义了复杂字符串匹配功能的模式,正则表达式语法需要一点时间来适应。

但是一旦习惯了它,会发现正则表达式在数据处理中几乎是必不可少的。

搜索功能

搜索功能是指查找指定正则表达式的一个或多个匹配项的操作。

re.search(<regex>, <string>, flags=0):扫描字符串以查找正则表达式的匹配项。这里的模式匹配仍然只是逐个字符的比较,与使用 in 运算符或 .find() 方法的示例几乎相同。

  import re

  re.search(r'(\d+)', 'Dynasty123Warriors')
  # Output: <re.Match object; span=(7, 10), match='123'>

  re.search(r'[a-z]+', '123Dynasty456', flags=re.IGNORECASE)
  # Output: <re.Match object; span=(3, 10), match='Dynasty'>

  re.search(r'\d+', 'Dynasty.Warriors')
  # Output: None

re.match(<regex>, <string>, flags=0):在字符串的开头查找正则表达式的匹配项。

re.search(r'\d+', '123DynastyWarriors')
# Output: <re.Match object; span=(0, 3), match='123'>

re.search(r'\d+', 'Dynasty123Warriors')
# Output: <re.Match object; span=(7, 10), match='123'>

re.match(r'\d+', '123DynastyWarriors')
# Output: <re.Match object; span=(0, 3), match='123'>

re.match(r'\d+', 'Dynasty123Warriors')
# Output: None

re.fullmatch(<regex>, <string>, flags=0):在整个字符串上查找正则表达式的匹配项。

re.fullmatch(r'\d+', '123Dynasty')
# Output: None

re.fullmatch(r'\d+', 'Dynasty123')
# Output: None

re.fullmatch(r'\d+', 'Dynasty123Warriors')
# Output: None

re.fullmatch(r'\d+', '123')
# Output: <re.Match object; span=(0, 3), match='123'>

re.search(r'^

\d+$', '123')
# Output: <re.Match object; span=(0, 3), match='123'>

re.findall(<regex>, <string>, flags=0):返回字符串中所有正则表达式匹配项的列表。

re.findall(r'\w+', '...Dynasty,,,,Warriors:%$dynasty//|')
# Output: ['Dynasty', 'Warriors', 'dynasty']

re.findall(r'#(\w+)#', '#Dynasty#.#Warriors#.dynasty')
# Output: ['Dynasty', 'Warriors']

re.findall(r'(\w+),(\w+)', 'Dynasty,Warriors,dynasty,warriors,sanguo,wushuang')
# Output: [('Dynasty', 'Warriors'), ('dynasty', 'warriors'), ('sanguo', 'wushuang')]

re.findall(r'(\w+),(\w+),(\w+)', 'Dynasty,Warriors,dynasty,warriors,sanguo,wushuang')
# Output: [('Dynasty', 'Warriors', 'dynasty'), ('warriors', 'sanguo', 'wushuang')]

re.finditer(<regex>, <string>, flags=0):返回产生正则表达式匹配项的迭代器。

it = re.finditer(r'\w+', '...Dynasty,,,,Warriors:%$dynasty//|')

next(it)
# Output: <re.Match object; span=(3, 6), match='Dynasty'>

next(it)
# Output: <re.Match object; span=(10, 13), match='Warriors'>

next(it)
# Output: <re.Match object; span=(16, 19), match='dynasty'>

# Raises StopIteration
next(it)

for match in re.finditer(r'\w+', '...Dynasty,,,,Warriors:%$dynasty//|'):
    print(match)
# Output:
# <re.Match object; span=(3, 6), match='Dynasty'>
# <re.Match object; span=(10, 13), match='Warriors'>
# <re.Match object; span=(16, 19), match='dynasty'>

替换函数

替换函数用于对字符串中的匹配项进行替换操作。

re.sub(<regex>, <repl>, <string>, count=0, flags=0):扫描字符串以查找正则表达式的匹配项,并用指定的替换字符串替换字符串的匹配部分,返回替换后的新字符串。

 # 字符串替换
 s = 'Dynasty.123.Warriors.789.dynasty'

 re.sub(r'\d+', '#', s)
 # Output: 'Dynasty.#.Warriors.#.dynasty'

 re.sub('[A-Za-z]+', '(*)', s)
 # Output: 'D(*).123.W(*).789.(*)'

 # 使用捕获组的文本替换编号的反向引用 \g<name>
 re.sub(r'(\w+),Warriors,dynasty,(\w+)', r'\2,Warriors,dynasty,\1', 'Dynasty,Warriors,dynasty,warriors')
 # Output: 'warriors,War

riors,dynasty,Dynasty'

 # 通过在尖括号内指定组号来引用编号反向引用
 re.sub(r'^Dynasty,(\w+),(\w+),warriors', r'Dynasty,\g<2>,\g<1>,warriors', 'Dynasty,Warriors,dynasty,warriors')
 # Output: 'Dynasty,dynasty,Warriors,warriors'

 # 使用空字符串替换零长度匹配,re.sub() 将替换字符串中的每个字符位置
 re.sub('x*', '-', 'Dynasty')
 # Output: '-D-y-n-a-s-t-y-'

 # 函数替换
 def f(match_obj):
     s = match_obj.group(0)  # 匹配字符串
     # 如果 s 中的所有字符都是数字,则返回 True
     if s.isdigit():
         return str(int(s) * 10)
     else:
         return s.upper()

 re.sub(r'\w+', f, 'Dynasty.10.Warriors.20.dynasty.30')
 # Output: 'Dynasty.100.Warriors.200.dynasty.300'

 # 限制替换次数
 re.sub(r'\w+', 'xxx', 'Dynasty.Warriors.dynasty.warriors')
 # Output: 'xxx.xxx.xxx.xxx'

 re.sub(r'\w+', 'xxx', 'Dynasty.Warriors.dynasty.warriors', count=2)
 # Output: 'xxx.xxx.dynasty.warriors'

re.subn(<regex>, <repl>, <string>, count=0, flags=0):与 re.sub() 类似,但也返回有关替换次数的信息。

re.subn(r'\w+', 'xxx', 'Dynasty.Warriors.dynasty.warriors')
# Output: ('xxx.xxx.xxx.xxx', 4)

re.subn(r'\w+', 'xxx', 'Dynasty.Warriors.dynasty.warriors', count=2)
# Output: ('xxx.xxx.dynasty.warriors', 2)

def f(match_obj):
    m = match_obj.group(0)
    if m.isdigit():
        return str(int(m) * 10)
    else:
        return m.upper()

re.subn(r'\w+', f, 'Dynasty.10.Warriors.20.dynasty.30')
# Output: ('Dynasty.100.Warriors.200.dynasty.300', 6)

实用功能

实用功能包括将字符串拆分为子字符串和转义正则表达式中的字符。

re.split(<regex>, <string>, maxsplit=0, flags=0):使用正则表达式作为分隔符将字符串拆分为子字符串。

# 将指定的字符串拆分为由逗号 (,)、分号 (;) 或斜线 (/) 字符分隔的子字符串
re.split('\s*[,;/]\s*', 'Dynasty,Warriors  ;  dynasty / warriors')
# Output: ['Dynasty', 'Warriors', 'dynasty', 'warriors']

string = 'Dynasty,Warriors  ;  dynasty / warriors'
regex = r'(?:\s*[,;/]\s*)'
re

.split(regex, string)
# Output: ['Dynasty', 'Warriors', 'dynasty', 'warriors']

re.escape(<regex>):转义正则表达式中的字符。

re.match('Dynasty^Warriors(dynasty)|warriors', 'Dynasty^Warriors(dynasty)|warriors')
# Output: None

re.match('Dynasty\^Warriors\(dynasty\)\|warriors', 'Dynasty^Warriors(dynasty)|warriors')
# Output: <re.Match object; span=(0, 16), match='Dynasty^Warriors(dynasty)|warriors'>

re.escape('Dynasty^Warriors(dynasty)|warriors') == 'Dynasty\^Warriors\(dynasty\)\|warriors'
# Output: True

re.match(re.escape('Dynasty^Warriors(dynasty)|warriors'), 'Dynasty^Warriors(dynasty)|warriors')
# Output: <re.Match object; span=(0, 16), match='Dynasty^Warriors(dynasty)|warriors'>

通过使用 re 模块提供的这些函数和方法,可以在 Python 中灵活且高效地处理字符串匹配和替换的需求。

06-05 08:44