python正则表达式匹配字符串

技术博客 (147) 2023-09-16 15:39:10

关注微信公众号(瓠悠笑软件部落),一起学习,一起摸鱼
python正则表达式匹配字符串 (https://mushiming.com/) 技术博客 第1张
相关资料:
re module
regular-expressions

使用步骤

  • import re 导入正则表达式模块
  • 用 re.compile() 函数创建一个 Regex 对象.(记着使用原始字符串, 字符串前面带r)
  • 将你要用于搜索的字符串传入 Regex 对象的 search() 方法中。这个方法将会返回一个 Match object.
  • 调用 Match object 的 group() 方法,将返回实际匹配到的文本

eg:匹配美国的号码

#! /usr/bin/python3
import re

phoneNumRegex = re.compile(r'\d{3}-\d{3}-\d{4}')
mo = phoneNumRegex.search('My number is 415-555-4242.')
print('Phone number found: ' + mo.group())

在线正则表达式

Grouping with Parentheses

假设您要将区号与电话号码的其余部分分开。添加括号将在正则表达式中创建组:
(\d{3})-(\d{3}-\d{4}). 然后你可以使用group() 匹配对象方法从一组的文字获取匹配的文本。正则表达式字符串中的第一组括号将是第1组。第二组括号将是第二组。通过将 整数 1 或者 2 作为参数传入 group() 方法中,你可以获取匹配到的文本的不同部分。如果传0, 或者不传,将会返回匹配的完整文本。

phoneNumberRegex = re.compile(r'(\d{3})-(\d{3}-\d{4})')
mo = phoneNumberRegex.search('My number is 415-555-4242.')
print(mo.group(1))
print(mo.group(2))
print(mo.group(0))
print(mo.group())

如果想一次获取所有的groups. 使用 groups() 方法。

print(mo.groups())
areaCode, mainNumber = mo.groups()
print(areaCode)
print(mainNumber)

由于 mo.groups() 返回了 一个包含多个值的元祖(tuple). 可以在一行里面对多个变量赋值:areaCode, mainNumber = mo.groups()。原括号在正则表达式里面有特殊的含义,如果要匹配原括号,需要使用反斜杠转义

phoneNumber2Regex = re.compile(r'(\(\d\d\d\)) (\d\d\d-\d\d\d\d)')
mo = phoneNumber2Regex.search('My phone number is (415) 555-4242.')
print(mo.group(1))
print(mo.group(2))

Matching Multiple Groups with the Pipe

|字符串叫做管道 pipe. 如果你想匹配多个表达式中的任意一个,就用管道。例如:正则表达式 r’Batman|Tian Fey’ 将会匹配 ‘Batman’ 或者 ‘Tina Fey’.
当Batman 和 Tina Fey 同时出现在搜寻的字符串中时,第一个出现的匹配文本将作为匹配对象的返回值。

#! /usr/bin/python3
import re

heroRegex = re.compile(r'Batman|Tina Fey')
mo1 = heroRegex.search('Batman and Tina Fey.')
print(mo1.group())

mo2 = heroRegex.search('Tina Fey and Batman.')
print(mo2.group())

### 输出的内容是
Batman
Tina Fey

如果想返回所有匹配上的。就用 findall() 方法。如果要匹配的单词有共同的开头字符串,那还可以这样玩。

batRegex = re.compile(r'Bat(man|mobile|copter|bat)')
mo = batRegex.search('Batmobile lost a wheel')
print(mo.group())
print(mo.group(1))

## 输出内容
Batmobile
mobile

如果你想匹配字符 ‘|’, 就需要用反斜杠转义。

optional matching with the question mark 用问号进行可选择匹配

#! /usr/bin/python3
import re

batRegex = re.compile(r'Bat(wo)?man')
mo1 = batRegex.search('The Adventures of Batman')
print(mo1.group())

mo2 = batRegex.search('The Adventures of Batwoman')
print(mo2.group())

### 输出内容是
Batman
Batwoman

你可以认为 ? 的含义是:Match zero or one of the group preceding this question mark.
如果你想匹配字符串?,需要使用反斜杠转义。

Matching zero or more with the star

‘*’ 字符串表示匹配 0个 或者 多个。

#! /usr/bin/python3
import re

batRegex = re.compile(r'Bat(wo)*man')
mo1 = batRegex.search('The Adventures of Batman')
print(mo1.group())

mo2 = batRegex.search('The Adventures of Batwoman')
print(mo2.group())

mo3 = batRegex.search('The Adventures of Batwowowowowowoman')
print(mo3.group())

# 输出内容
Batman
Batwoman
Batwowowowowowoman

matching one or more with the plus

‘+’ 字符表示 “匹配1个或者多个" 必须至少出现一次,不是可选的。

#! /usr/bin/python3
import re

batRegex = re.compile(r'Bat(wo)+man')
mo1 = batRegex.search('The Adventures of Batwoman')
print(mo1.group())

mo2 = batRegex.search('The Adventures of Batwowowowowoman')
print(mo2.group())

mo3 = batRegex.search('The Adventures of Batman')
print(mo3 == None)

# 输出内容
Batwoman
Batwowowowowoman
True

Matching Specific Repetitions with Curly Brackets

在花括号里面指定最小出现的次数和最大出现的次数。以此匹配重复出现字符串的不同情况。例如Ha{1,3} 将匹配出现1次到3次的字符串。

The findall() method

#! /usr/bin/python3
import re

phoneNumRegex = re.compile(r'\d{3}-\d{3}-\d{4}')
print(phoneNumRegex.findall('Cell: 415-555-9999 Work: 212-555-0000'))
phoneNum2Regex = re.compile(r'(\d{3})-(\d{3})-(\d{4})')
print(phoneNum2Regex.findall('Cell: 415-555-9999 Work: 212-555-0000'))

# outputs
['415-555-9999', '212-555-0000']
[('415', '555', '9999'), ('212', '555', '0000')]
  • 如果表达式里面没有 groups, 返回的是列表
  • 如果表达式里面有 groups. 返回的是元组 tuple

Matching newlines with the Dot Character

点星( .* ) 将会匹配所有的字符,直到遇到换行符。通过传递 re.DOTALL 做为第二个参数传递给 re.compile(). 就可以匹配所有的字符了,甚至包括换行符.

#! /usr/bin/python3
import re
noNewlineRegex = re.compile('.*')
match = noNewlineRegex.search('Serve the public trust.\n Protect the innocent. \nUpload the law.').group()
print(match)

newlineRegex = re.compile('.*', re.DOTALL)
match_new = newlineRegex.search('Serve the public trust.\nProtect the innocent.\nUphold the law.').group()
print(match_new)

#输出内容
Serve the public trust.
Serve the public trust.
Protect the innocent.
Uphold the law.

Review of Regex Symbols

  • The ? matches zero or one of the preceding group.
  • The * matches zero or more of the preceding group.
  • The + matches one or more of the preceding group.
  • The {n} matches exactly n of the preceding group.
  • The {n,} matches n or more of the preceding group.
  • The {,m} matches 0 to m of the preceding group.
  • The {n,m} matches at least n and at most m of the preceding group.
  • {n,m}? or *? or +? performs a nongreedy match of the preceding group.
  • ^spam means the string must begin with spam.
  • spam$ means the string must end with spam.
  • The . matches any character, except newline characters.
  • \d , \w , and \s match a digit, word, or space character, respectively.
  • \D , \W , and \S match anything except a digit, word, or space character,
  • respectively.
  • [abc] matches any character between the brackets (such as a, b, or c).
  • [^abc] matches any character that isn’t between the brackets.

不区分大小写匹配字符

#! /usr/bin/python3
import re
rebocop = re.compile(r'rebocop', re.I)
match = rebocop.search('ReboCop is part man, part machine, all cop.').group()
print(match)

管理复杂的正则表达式

如果您需要匹配的文本模式很简单,则正则表达式很好。但是匹配复杂的文本模式可能需要冗长,复杂的正则表达式。您可以通过告诉 re.compile() 函数来缓解这种情况忽略正则表达式字符串中的空格和注释。可以通过将变量 re.VERBOSE 作为传递来启用此“详细模式” re.compile()的第二个参数。

#! /usr/bin/python3
import re

phoneRegex = re.compile(r'''( (\d{3}|\(\d{3}\))? # area code (\s|-|\.)? # separator \d{3} # first 3 digits (\s|-|\.) # separator \d{4} # last 4 digits (\s*(ext|x|ext.)\s*\d{2,5})? #extension )''', re.VERBOSE)

请注意前一个示例如何使用三引号语法(’’’)创建一个多行字符串,以便您可以将正则表达式定义分布在多行上,使其更加清晰。正则表达式字符串中的注释规则与常规Python代码:#符号及其后的所有内容线被忽略。此外,正则表达式的多行字符串内的额外空格不被视为要匹配的文本模式的一部分。这使您可以组织正则表达式,以便更容易阅读。

从粘贴板的文字中提取邮箱和手机号码

#! /usr/bin/python3
# phoneAndEmail.py - Finds phone numbers and email address on the chipboard.

import pyperclip, re

americaPhoneRegex = re.compile(r'''( (\d{3}|\(\d{3}\))? # area code (\s|-|\.)? # separator (\d{3}) # first 3 digits (\s|-|\.) # separator (\d{4}) # last 4 digits (\s*(ext|x|ext.)\s*(\d{2,5}))? # extension )''', re.VERBOSE)    

chinesePhoneRegex = re.compile(r'1\d{10}')

emailPhoneRegex   = re.compile(r'''( [a-zA-Z0-9._%+-]+ # username @ # @ symbol [a-zA-Z0-9.-]+ # domain name (\.[a-zA-Z]{2,4}) # dot-something )''', re.VERBOSE)


# Find matches in clipboard text.
text = str(pyperclip.paste())
matches = []
for groups in americaPhoneRegex.findall(text):
    phoneNum = '-'.join([groups[1], groups[3], groups[5]])
    if groups[8] != '':
        phoneNum += ' x' + groups[8]
    matches.append(phoneNum)

for groups in emailPhoneRegex.findall(text):
    matches.append(groups[0])

for groups in chinesePhoneRegex.findall(text):
    matches.append(groups[0])

# copy results the clipboard. 
if len(matches) > 0:
    pyperclip.copy('\n'.join(matches))
    print('Copied to clipboard:')
    print('\n'.join(matches))
else:
    print('No phone numbers or email addresses found.')
THE END

发表回复