如何使用正则表达式提取文本块而不将文本块分成几行

时间:2019-03-24 20:14:13

标签: python regex string

我想使用python提取一本书的章节。我已经标记了每本书的章节,指示每章的开始和结束。本章开始的标签为[@introS],本章结束的标签为[@ introEnd @]。我的代码的目标是提取标记之间的所有内容(对应于每个章节的文本),并要求用户命名每个章节并写入文件。但是,当我打印匹配结果时,将打印整个文本。仅当开始标记和结束标记由行分隔时,此代码才有效。

输入示例:

  

同伴套房假名没有出现在维恩·德·帕勒(feu M. John)   巴兰坦,法国德沃尔特·斯科特出版社   Discussion avec sonconfrèrede Londres,chacun $ d'eux soutenant que   儿子Jedediah Cleishbothamétaitle vrai Simon Pure。 $ CHAPITRE PREMIER。   $ [@ introS] C'est aux moines qu'on doit la迷信,$ La nuit des   长期以来的历史与历史   巴黎圣母院。 $-Jebéniscomme vous la bienfaisante main $ Qui   巴黎人的风土人情:$ Mais sur les Moines seuls   在拒绝的情况下,$ C'estàmaiison trop tementment反对。   $ Je croirais aussi bien que Molly Warburton,$ Traversant cette nuit   莱昂河畔巴顿河畔莱斯,因奥拉河畔阿夫雷弗·基隆达河畔诺萨   têtes。 $ Ancienne喜剧片。 $ E village auquel le manuscrit dubénédictin   Donne le nom $ de Kennaquhair porte lamêmeterminaison celtique qu'on   $ trouve dans Traquhair,Caquhair等广告位。乐   萨万特·查默斯(Savant Chalmers)”的原价$-象征性的价格   d'unerivière; et les nombreux $détoursque fait la Tweedprèsde ce   village rendent l'étymologie$ assez vraisemblable [@ introEnd @]。   [@introS] Longtemps Kennaquhair拥有$ superbemonastère的资格   de Sainte-Marie,fondépar David I“,roi d'Écosse,$ sous lerègne   杜克大学,非货币性财富$ de Melrose,de   吉德堡(Jedburgh et de Kelso)。 Les DomainesConsidérables$ que ce monarque   协议潜水员宗教诉讼$ firentdécernerle   莫里斯圣雷峰峰顶照片   临时的,后代的后裔,-可获得的收入   圣三一圣库拉讷河畔。 '在peut的后裔présumerque   大卫·奥古斯都王子,$ ne fut pasdéterminéseulement par   宗教的大图案$•_ / $ [@ introEnd @]。 [@introS]   Google既有旅行社也有合作书目‡   全国公共事业组织   rendre $ ainsi无障碍设施‡tous。生活的乐趣   简易性原则   加德满都爱国者。 $ Il s'agit toutefois d'un projetco˚teux。   具有同等效力的扩散性资源   处置不便的人   普罗旺斯地区埃文图勒斯滥用职权保护地点   marchands层,instaurant des $ contraintes技术的通知   亲戚需要自动取款机[@introEnd @]。

我尝试过的代码如下。

我尝试使用match,但是我不确定这将是最好的方法...也许尝试findall还是search?

import re


def separate_chapters ():

    pat = re.compile('(?<=\[@introS\]).+?(?=\[@introEnd@\])')

    with open('text1_scott.txt') as file:

        for i in filter(pat.match, file):
            print(i)
            inp = input("write text to a file? Y|N: ")
            if inp != "Y":
                continue

            file_name = input("Name of your file: ")

            with open(file_name, "w") as out_file:
                out_file.write(i)
            print("text {} written to a file".format(i))     


separate_chapters()

我不想将各章分开放在不同的行中...我想提取整个文本块,即使同一行中有标签。...该怎么做?

1 个答案:

答案 0 :(得分:4)

您的模式有点不正确。您需要转义[],也不需要转义@,因为@在正则表达式中不是特殊字符。另外,要捕获这些开始标记和结束标记之间的内容,.是不够的,因为它仅捕获一个字符,因此您需要使用环顾四周并使用.+?来捕获它们之间的文本。贪婪的态度。尝试使用此正则表达式,

(?<=\[@introS\]).+?(?=\[@introEnd@\])

在这里,(?<=\[@introS\])的积极眼光确保了将要捕获的任何文本均以字面意义上的[@introS]文本开头,然后.+?捕获了尽可能少的任何一个或多个字符,而{{ 1}}积极的前瞻性确保,无论被捕获的内容是紧跟着(?=\[@introEnd@\])

Online Demo

编辑:

您的代码中有几个问题。

  • 您的正则表达式声明不正确,因为我已经告诉过您,并且您已修复该字符串,但未将其引用。
  • 您需要在[@introEnd@]对象上调用read()函数以从文件中检索字符串
  • 您可以只使用简单的file而不是match,其中match的工作原理有所不同,并尝试使用正则表达式匹配全文
  • 由于文件包含Unicode字符,因此您需要使用findall来读写文件。

这是您代码的更新后的工作副本,

encoding="utf-8"

执行得很好,并在提示输入文件名时在输入的文件名中写入章节文本。大约凌晨3:00,这里感觉太累了,要睡觉了,因此现在可能无法回答任何进一步的查询,但是肯定会在早上进行。希望您不会再遇到任何问题。