Python - 匹配多行文本块的正则表达式


本文讨论了在多行字符串中搜索特定模式的方法。 该解决方案折衷了已知和未知模式的几种方法,并解释了匹配模式的工作原理。


编写正则表达式以匹配多行字符串的原因

假设我们有以下文本块:

Any compiled body of information is known as a data set. Depending on the situation's specifics, this may be a database or a simple array.\n
\n
IBM first used the term "data set," which meant essentially the same thing as "file," to describe a collection of related records.

从上面给出的文本块中,需要找到起始文本,文本在下面几行呈现。 重要的是要注意 \n 表示换行符而不是文字文本。

总而言之,我们想要跨多行查找和匹配文本,忽略文本之间可能出现的任何空行。 在上述文本的情况下,它应该返回 Any compiled body… 行,并且 IBM 首先在单个正则表达式查询中使用了 term… 行。


匹配多行字符串的可能解决方案

在讨论这个特定问题的解决方案之前,必须了解 regex(正则表达式)API 的不同方面,尤其是那些在整个解决方案中经常使用的方面。

那么,让我们从 re.compile() 开始吧。

Python re.compile() 方法

re.compile() 将正则表达式模式编译为正则表达式对象,我们可以使用该对象与 match()、search() 和其他描述的方法进行匹配。

re.compile() 相对于未编译模式的优势之一是可重用性。 我们可以多次使用已编译的表达式,而不是为每个未编译的模式声明一个新字符串。

import re as regex

pattern = regex.compile(".+World")
print(pattern.match("Hello World!"))
print(pattern.search("Hello World!"))

输出:

<re.Match object; span=(0, 11), match='Hello World'>
<re.Match object; span=(0, 11), match='Hello World'>

Python re.search() 方法

re.search() 在字符串中搜索匹配项,如果找到则返回一个 Match 对象。

如果存在多个匹配项,我们将返回第一个实例。

我们也可以不使用re.compile()直接使用,适用于只需要查询一次的情况。

import re as regex

print(regex.search(".+World", "Hello World!"))

输出:

<re.Match object; span=(0, 11), match='Hello World'>

Python re.finditer() 方法

re.finditer() 匹配字符串中的模式并返回一个迭代器,该迭代器为所有非重叠匹配项提供 Match 对象。

然后我们可以使用迭代器迭代匹配项并执行必要的操作; 匹配按照它们在字符串中从左到右的找到方式排序。

import re as regex

matches = regex.finditer(r'[aeoui]', 'vowel letters')
for match in matches:
    print(match)

输出:

<re.Match object; span=(1, 2), match='o'>
<re.Match object; span=(3, 4), match='e'>
<re.Match object; span=(7, 8), match='e'>
<re.Match object; span=(10, 11), match='e'>

Python re.findall() 方法

re.findall() 返回字符串中模式的所有非重叠匹配项的列表或元组。 从左到右扫描一个字符串。 并且匹配按照它们被发现的顺序返回。

import re as regex
 
# Find all capital words
string= ',,21312414.ABCDEFGw#########'
print(regex.findall(r'[A-Z]+', string))

输出:

['ABCDEFG']

Python re.MULTILINE 方法

re.MULTILINE 的一个显着优势是它允许 ^ 在每一行的开头而不是仅在字符串的开头搜索模式。

Python 正则表达式符号

当以复杂的方式使用时,正则表达式符号很快就会变得非常混乱。 以下是我们解决方案中使用的一些符号,以帮助更好地理解这些符号的基本概念。

  • ^ 断言行首的位置
  • 字符串匹配(区分大小写的)字符“字符串”
  • . 匹配所有字符(用于行终止的符号除外)
    • 尽可能频繁地匹配先前给定的标记。
  • \n 匹配换行符
  • \r 匹配一个 (CR) 回车符
  • ? 与前一个标记匹配 0-1 次
  • +? 尽可能少地匹配前一个标记 1 到无限次。
  • a-z 匹配 a 和 z 之间范围内的单个字符(区分大小写)

使用 re.compile() 匹配 Python 中的多行文本块

让我们了解使用不同的模式。

示例代码:

import re as regex

multiline_string = "Regular\nExpression"
print(regex.search(r'^Expression', multiline_string, regex.MULTILINE))

输出:

<re.Match object; span=(8, 18), match='Expression'>

上面的表达式首先断言它在行首的位置(由于 ^),然后搜索“表达式”的确切出现。

使用 MULTILINE 标志确保检查每一行是否出现“表达式”,而不仅仅是第一行。

示例代码:

import re as regex

data = """Any compiled body of information is known as a data set. Depending on the situation's specifics, this may be a database or a simple array.\n
\n
IBM first used the term "data set," which meant essentially the same thing as "file," to describe a collection of related records.
"""

result = regex.compile(r"^(.+)(?:\n|\r\n)+((?:(?:\n|\r\n?).+)+)", regex.MULTILINE)

print(result.search(data)[0].replace("\n", ""))

输出:

Any compiled body of information is known as a data set. Depending on the situation's specifics, this may be a database or a simple array.IBM first used the term "data set," which meant essentially the same thing as "file," to describe a collection of related records.

正则表达式可以分解并简化为更小的块以提高可读性:

在第一个捕获组 (.+) 中,每个字符都在行中匹配(除了与行终止符对应的任何符号); 这个过程尽可能频繁地进行。

之后,在非捕获组 (?:\n|\r\n) 中,尽可能多地匹配一个行结束符或者一个行结束符加回车。

至于第二个捕获组 ((?:(?:\n|\r\n?).+)+,它由一个非捕获组 (?:(?:\n|\r\n? ).+)+ 换行符或换行符加回车最多匹配一次。

每个字符都在非捕获组之外匹配,不包括行终止符。 尽可能多地执行此过程。

示例代码:

import re as regex

data = """Regex In Python

Regex is a feature available in all programming languages used to find patterns in text or data.
"""

query=regex.compile(r"^(.+?)\n([\a-z]+)",regex.MULTILINE)

for match in query.finditer(data):
    topic, content = match.groups()
    print ("Topic:",topic)
    print ("Content:",content)

输出:

Topic: Regex In Python
Content: 
Regex is a feature available in all programming languages used to find patterns in text or data.

上面的表达式可以解释如下:

在第一个捕获组 (.+?) 中,尽可能少地匹配所有字符(除了行终止符,和以前一样)。 之后,匹配单个换行符 \n

匹配换行符后,在第二个捕获组 (\n[a-z ]+) 中进行如下操作。 首先,匹配换行符,然后尽可能多次匹配 a-z 之间的字符。

使用 re.findall() 在 Python 中匹配多行文本块

示例代码:

import re as regex

data = """When working with regular expressions, the sub() function of the re library is an invaluable tool.

the subroutine looks over the string for the given pattern and applies the given replacement to all instances where it is found.
"""

query = regex.findall('([^\n\r]+)[\n\r]([a-z \n\r]+)',data)

for results in query:
    for result in results:
        print(result.replace("\n",""))

输出:

When working with regular expressions, the sub() function of the re library is an invaluable tool.
the subroutine looks over the string for the given pattern and applies the given replacement to all instances where it is found

为了更好地理解正则表达式的解释,让我们按每个组对其进行分解,看看每个部分的作用。

在第一个捕获组 ([^\n\r]+) 中,尽可能多地匹配所有字符,不包括换行符或回车符。

之后,当字符是表达式 [\n\r] 中的回车符或换行符时进行匹配。

在第二个捕获组 ([a-z \n\r]+) 中,a-z 或换行符或回车符之间的字符尽可能多地匹配。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

迹忆客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值