如何使用findall()匹配在字符串中重复n次的模式?

时间:2019-03-28 06:11:36

标签: python-3.x

我正在尝试解析一个重复的字符串,并从中找到与我的findall()函数中的模式匹配的多个匹配项。

基本上,我想从字符串中提取玩家的名字。它们之间用逗号分隔,并且播放器的姓氏前带有“和”。我试图减少逗号部分,但是由于某种原因,即使我添加了findall()*似乎也没有重复匹配模式。

x = re.findall('Players(?:\s([A-Z]+[a-z]+)),*', 'Players Jeremiah, Lou, Martha and Kay,')

自从我坚持使用逗号以来,我还没有把and部分讲完,但是从上面的代码中,我觉得x至少应该抓住耶利米,娄和玛莎。我的代码只能捕获耶利米。

2 个答案:

答案 0 :(得分:0)

您的模式以Players...开头,因此仅匹配一次,因为您的字符串中只有一个Players

这将是处理and部分的正确模式:

  • 玩家名称是非空格或逗号的任何字符,
  • 必须在其后加上逗号或空格+ and
import re

x = re.findall(r'([^\s,]+)(?:,|\s+and)',
               'Players Jeremiah, Lou, Martha and Kay,')

print(x)

试运行:

$ python3 dummy.py
['Jeremiah', 'Lou', 'Martha', 'Kay']

更新以匹配OP给出的更多正则表达式不再是一个正则表达式:

  • 匹配必需的前缀Players并提取其余的
  • 匹配可选的后缀,例如are ...,然后剥离
  • 在剩余句子中检测玩家名称
    • 从单词边界开始
    • 以大写字母开头
    • 跟着一个或多个小写字母
    • 在单词边界处结束
import re;

for input in (
        'Jeremiah, Lou, Martha and Kay,',
        'Players Jeremiah, Lou, Martha and Kay,',
        'The Players are Martha, Joe, Toby and Kay.',
        'The Players Martha, Joe and Toby are German.',
        'The Players Martha, Joe and Toby are German,',
    ):

    # strip mandatory prefix
    match = re.search('Players(.*)', input)
    if not match:
        continue
    #print(match[1])

    # strip optional postfix
    postfix = re.search('(.*)(?:\s+(?:are)\s+\S+[,.])$', match[1])
    if postfix:
        match = postfix
    #print(match[1])

    result = re.findall(r'(\b[A-Z][a-z]+\b)', match[1])
    print(input, '->', result)

试运行:

$ python3 dummy.py
Players Jeremiah, Lou, Martha and Kay, -> ['Jeremiah', 'Lou', 'Martha', 'Kay']
The Players are Martha, Joe, Toby and Kay. -> ['Martha', 'Joe', 'Toby', 'Kay']
The Players Martha, Joe and Toby are German. -> ['Martha', 'Joe', 'Toby']
The Players Martha, Joe and Toby are German, -> ['Martha', 'Joe', 'Toby']

答案 1 :(得分:0)

我想您基本上是在寻找专有名词的模式。在您使用的模式中,它仅捕获“耶利米”,因为您的模式'Players(?:\s([A-Z]+[a-z]+)),*'专门在单词“玩家”之后寻找专有名词。

请改用以下模式: (?!^[A-Z]\w+)(?<![.]\s)([A-Z]\w+)

它寻找专有名词,但排除句子开头的大写单词。

  

([A-Z]\w+)匹配大写字母

     

(?<![.]\s)确保我们不会选择句号和空格之后的任何内容

     

(?!^[A-Z]\w+)在字符串开头保留大写单词(例如,在新行中)

警告 如果您的结果需要100%的精度,那么广义模式可能不是理想的选择。如果您的句子以名称开头,则此模式可能会低估名称的数量。

测试here