【问题标题】:In Python, how do I extract multiple blocks of text that begin with same pattern, but no distinct end?在 Python 中,如何提取以相同模式开头但没有不同结尾的多个文本块?
【发布时间】:2020-03-12 18:44:30
【问题描述】:

给定一个测试字符串:

teststr= 'chapter 1 Here is a block of text from chapter one.  chapter 2 Here is another block of text from the second chapter.  chapter 3 Here is the third and final block of text.'

我想创建一个这样的结果列表:

result=['chapter 1 Here is a block of text from chapter one.','chapter 2 Here is another block of text from the second chapter.','chapter 3 Here is the third and final block of text.']

使用re.findall('chapter [0-9]',teststr)

我收到['chapter 1', 'chapter 2', 'chapter 3']

如果我想要的只是章节编号,那很好,但我想要章节编号加上直到下一个章节编号的所有文本。在最后一章的情况下,我想得到章号和一直到最后的文字。

尝试re.findall('chapter [0-9].*',teststr) 会产生贪婪的结果: ['chapter 1 Here is a block of text from chapter one. chapter 2 Here is another block of text from the second chapter. chapter 3 Here is the third and final block of text.']

我不擅长正则表达式,因此我们将不胜感激。

【问题讨论】:

  • pattern = re.compile(r'chapter (?:(?!\s+chapter \d+).)+') 并使用pattern.findall
  • 您可以通过在开头添加一些不包含“章节”的文本来改进您的示例。要识别匹配项,必须“章后跟一个空格,一个或多个数字,然后至少有一个空格?“章”可以是“章”吗?这些问题源于您是根据单个示例提出问题的事实. 这很少使问题不明确。您需要用文字准确而明确地陈述您的问题,然后使用一个或多个示例进行说明...
  • ..这是一个可能的问题陈述示例,旨在完整且明确(但只是我对您想要的内容的猜测):“我希望提取所有以 ' 开头的字符串[cC]hapter d+ ',其中 '[cC]' 表示一个 'c' 或一个 'C' 并且 'd+' 表示一个或多个数字,并以句点结尾,后跟零个或多个空格,然后是字符串或另一个字符串 '[cC]hapter d+ '"。
  • 为了不区分大小写,pattern = re.compile(r'(?i)chapter (?:(?!\s+chapter \d+).)+') 然后使用matches = pattern.findall(teststr)
  • 也许re.split(r'(?!^)(?=chapter \d)', teststr) 就够了?见the Python demo

标签: python regex findall


【解决方案1】:

一般来说,提取正则表达式看起来像

(?s)pattern.*?(?=pattern|$)

或者,如果pattern 位于行首,

(?sm)^pattern.*?(?=\npattern|\Z)

在这里,你可以使用

re.findall(r'chapter [0-9].*?(?=chapter [0-9]|\Z)', text)

this regex demo详情

  • chapter [0-9] - chapter + 空格和数字
  • .*? - 任何零个或多个字符,尽可能少
  • (?=chapter [0-9]|\Z) - 正向预测,匹配紧跟在 chapter、空格、数字或整个字符串结尾的位置。

这里,由于文本以关键字开头,您可以使用

import re
teststr= 'chapter 1 Here is a block of text from chapter one.  chapter 2 Here is another block of text from the second chapter.  chapter 3 Here is the third and final block of text.'
my_result = [x.strip() for x in re.split(r'(?!^)(?=chapter \d)', teststr)]
print( my_result )
# => ['chapter 1 Here is a block of text from chapter one.', 'chapter 2 Here is another block of text from the second chapter.', 'chapter 3 Here is the third and final block of text.']

请参阅Python demo(?!^)(?=chapter \d) 正则表达式的意思是:

  • (?!^) - 找到一个不在字符串开头的位置并且
  • (?=chapter \d) - 紧随其后的是 chapter、空格和任何数字。

该模式用于在找到的位置拆分字符串,并且不消耗任何字符,因此,在列表理解中,结果会从空格中删除。

【讨论】:

    【解决方案2】:

    如果您不必使用正则表达式,请尝试以下操作:

    def split(text):
        chapters = []
    
        this_chapter = ""
        for i, c in enumerate(text):
            if text[i:].startswith("chapter ") and text[i+8].isdigit():
                if this_chapter.strip():
                    chapters.append(this_chapter.strip())
                this_chapter = c
            else:
                this_chapter += c
    
        chapters.append(this_chapter.strip())
    
        return chapters
    
    print(split('chapter 1 Here is a block of text from chapter one.  chapter 2 Here is another block of text from the second chapter.  chapter 3 Here is the third and final block of text.'))
    

    输出:

    ['chapter 1 Here is a block of text from chapter one.', 'chapter 2 Here is another block of text from the second chapter.', 'chapter 3 Here is the third and final block of text.']
    

    【讨论】:

      【解决方案3】:

      您正在寻找re.split。假设最多 99 章:

      import re
      teststr= 'chapter 1 Here is a block of text from chapter one.  chapter 2 Here is another block of text from the second chapter.  chapter 3 Here is the third and final block of text.'
      
      chapters = [i.strip() for i in re.split('chapter \d{1,2}', teststr)[1:]]
      

      输出:

      ['Here is a block of text from chapter one.',
       'Here is another block of text from the second chapter.',
       'Here is the third and final block of text.']
      

      【讨论】:

      • 现在修复了
      猜你喜欢
      • 1970-01-01
      • 2023-03-23
      • 2016-02-19
      • 1970-01-01
      • 1970-01-01
      • 2023-03-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多