根据标点或驼峰命名分割句子

1 投票
1 回答
554 浏览
提问于 2025-04-18 14:59

我在Python中有一个很长的字符串,想把它分成一个句子的列表。不过,有些句子之间缺少标点符号和空格。

举个例子

我车库里有9只羊视频游戏超级酷。

我搞不清楚怎么用正则表达式把这两个句子分开!这让我很头疼。

还有一些句子是有正确标点的,所以我想做几个不同的正则表达式,每个用来分开不同风格的组合。

输入

我车库里有9只羊视频游戏超级酷。有些花生会唱歌,虽然它们的味道比听起来好得多!

输出

['我车库里有9只羊', '视频游戏超级酷。', '有些花生会唱歌,虽然它们的味道比听起来好得多!']

谢谢!

1 个回答

3

位置拆分:使用 regex 模块

我会给你提供一个“拆分”和一个“匹配所有”的选项。我们先从“拆分”开始。

在很多引擎中,但不是Python的 re 模块,你可以在一个零宽匹配的位置进行拆分。

在Python中,如果要在某个位置拆分,我会使用Matthew Barnett的优秀regex 模块,它的功能远远超过Python默认的 re 引擎。这个模块是我在Python中使用的默认正则表达式引擎。

根据你的输入,你可以使用这个正则表达式:

(?V1)(?<=[a-z])(?=[A-Z])|(?<=[.!?]) +(?=[A-Z])

注意,如果你有格式奇怪的缩写,比如 B. B. C.,我们需要对这个表达式进行调整。

示例Python代码:

string = "I have 9 sheep in my garageVideo games are super cool. Some peanuts can sing, though they taste a whole lot better than they sound!"
result = regex.split("(?V1)(?<=[a-z])(?=[A-Z])|(?<=[.!?]) +(?=[A-Z])", string)
print(result)

输出:

['I have 9 sheep in my garage', 
'Video games are super cool.', 
'Some peanuts can sing, though they taste a whole lot better than they sound!']

解释

  • (?V1) 告诉引擎使用新的行为,这样我们就可以在零宽匹配的位置进行拆分。
  • (?<=[a-z])(?=[A-Z]) 匹配一个位置,在这个位置,前面是小写字母,后面是大写字母。
  • | 或者...
  • (?<=[.!?]) +(?=[A-Z]) 匹配一个或多个空格 +,在这个位置,前面是句号、感叹号或问号和一个空格,后面是一个大写字母。

选项2:使用 findall(同样使用 regex 模块)

因为“拆分”和“匹配所有”操作是同一个问题的两个方面,你可以这样做:

print(regex.findall(r".+?(?:(?<=[.!?])|(?<=[a-z])(?=[A-Z]))",string))

再次强调,这在 re 中是无法实现的(因为它会跳过第二个句子开头的 V,也就是 Video)。

撰写回答