【问题标题】:Regular expression to extract chunks of text from a text file?正则表达式从文本文件中提取文本块?
【发布时间】:2020-01-29 01:32:18
【问题描述】:

我需要使用正则表达式从 Python 中的文本文件中提取标题及其下方的文本块,但我发现这很困难。

我将此PDF 转换为文本,现在它看起来像这样:

到目前为止,我已经能够使用以下正则表达式获取所有数字标题(12.4.5.4、12.4.5.6、13、13.1、13.1.1、13.1.12):

import re

with open('data/single.txt', encoding='UTF-8') as file:

    for line in file:
        headings = re.findall(r'^\d+(?:\.\d+)*\.?', line)
        print(headings)`

我只是不知道如何获取这些标题的措辞部分或它们下面的文本段落。

编辑 - 这是文本:

I.S. EN 60601-1:2006&A1:2013&AC:2014&A12:2014

60601-1 © IEC:2005 60601-1 © IEC:2005

– 337 – – 169 –

12.4.5.4 产生诊断或治疗辐射的其他 ME 设备 适用时,制造商应在风险管理过程中解决 与产生诊断或治疗辐射的 ME 设备相关的风险,除了 用于诊断 X 射线和放射治疗(见 12.4.5.2 和 12.4.5.3)。

通过检查风险管理文件来检查合规性。

12.4.6 诊断或治疗声压 适用时,制造商应在风险管理过程中解决 与诊断或治疗声压相关的风险。

通过检查风险管理文件来检查合规性。

13 * 危险情况和故障条件

13.1 特定的危险情况

  • 一般

13.1.1 当应用 4.7 中所述和 13.2 中列出的单一故障条件时,一个 时间,13.1.2 至 13.1.4(含)中的任何危险情况都不会发生在 ME 设备。

任何一个组件的故障,可能导致危险情况,是 在 4.7 中描述。

  • 排放、外壳变形或超过最高温度

13.1.2 不得发生以下危险情况: – 在危险中排放火焰、熔融金属、有毒或可燃物质

数量;

– 外壳变形到不符合 15.3.1 的程度; -

应用部分的温度超过表 24 中确定的允许值时, 按 11.1.3 所述进行测量; ME 设备部件的温度不是应用部件,但可能是 触摸时,测量和调整时超过表 23 中的允许值 在 11.1.3 中描述;

——

– 超过表 22 中确定的“其他组件和材料”的允许值 乘以 1,5 - 12,5 °C。绕组限制见表 26、表 27 和表 31。 在所有其他情况下,适用表 22 的允许值。

应使用 11.1.3 中描述的方法测量温度。

4.7、8.1 b)、8.7.2 和 13.2.2 中的单一故障条件,关于排放 火焰、熔融金属或可燃物质,不得应用于零部件 在哪里: – 结构或供电电路限制了 SINGLE FAULT 中的功耗

条件小于 15 W 或能量耗散小于 900 J。

【问题讨论】:

  • 您能否在问题中添加data/single.txt 的文本而不是pdf 的链接?你想精确匹配什么?只有 1 个后续段落还是段落编号后面的文本?
  • 当然!现在刚刚添加了文本。
  • 如果您想将段落与以下文本匹配,直到下一个尝试^\d+(?:\.\d+)* +.*(?:\r?\n(?!\d+(?:\.\d+)* ).*)* regex101.com/r/eHXZ8x/1

标签: python regex text text-extraction


【解决方案1】:

也许,

^(\d+(?:\.\d+)*)\s+([\s\S]*?)(?=^\d+(?:\.\d+)*)|^(\d+(?:\.\d+)*)\s+([\s\S]*)

可能有点接近获得我猜测的那些所需文本。


这里我们只需要查找开头的行,

^(\d+(?:\.\d+)*)\s+

然后,我们只需使用之后收集任何东西

([\s\S]*?)

直到下一行,

(?=^\d+(?:\.\d+)*)

然后,我们可能会也可能不会,取决于我们输入的样子,只剩下一个最后一个元素,我们将使用这个最后一个来收集它:

^(\d+(?:\.\d+)*)\s+([\s\S]*)

然后我们将(使用|)更改为先前的表达式。

尽管这种方法的代码很简单,但由于我们使用的是环视,所以它的性能相当慢,所以the other answer here 要好得多,如果时间复杂度是一个问题,这很可能是。

Demo 1

测试

import re

regex = r"^(\d+(?:\.\d+)*)\s+([\s\S]*?)(?=^\d+(?:\.\d+)*)|^(\d+(?:\.\d+)*)\s+([\s\S]*)"
string = """

I.S. EN 60601-1:2006&A1:2013&AC:2014&A12:2014

60601-1 © IEC:2005 
60601-1 © IEC:2005

– 337 – 
– 169 –

12.4.5.4  Other ME EQUIPMENT producing diagnostic or therapeutic radiation 
When  applicable,  the  MANUFACTURER  shall  address  in  the  RISK  MANAGEMENT PROCESS  the 
RISKS associated  with  ME EQUIPMENT  producing  diagnostic or therapeutic radiation  other  than 
for diagnostic X-rays and radiotherapy (see 12.4.5.2 and 12.4.5.3). 

Compliance is checked by inspection of the RISK MANAGEMENT FILE.

12.4.6  Diagnostic or therapeutic acoustic pressure 
When  applicable,  the  MANUFACTURER  shall  address  in  the  RISK  MANAGEMENT PROCESS  the 
RISKS associated with diagnostic or therapeutic acoustic pressure. 

Compliance is checked by inspection of the RISK MANAGEMENT FILE.

13  *  HAZARDOUS SITUATIONS and fault conditions

13.1  Specific HAZARDOUS SITUATIONS

*  General 

13.1.1 
When  applying  the  SINGLE  FAULT  CONDITIONS  as  described  in  4.7  and listed  in  13.2,  one  at  a 
time,  none  of  the  HAZARDOUS  SITUATIONS  in  13.1.2  to  13.1.4  (inclusive)  shall  occur  in  the 
ME EQUIPMENT.

The failure of any one component at a time, which could result in a  HAZARDOUS  SITUATION, is 
described in 4.7. 

*  Emissions, deformation of ENCLOSURE or exceeding maximum temperature 

13.1.2 
The following HAZARDOUS SITUATIONS shall not occur: 
–  emission  of  flames,  molten  metal,  poisonous  or  ignitable  substance  in  hazardous 

quantities; 

–  deformation of ENCLOSURES to such an extent that compliance with 15.3.1 is impaired; 
– 

temperatures  of  APPLIED  PARTS exceeding  the  allowed  values  identified  in  Table  24  when 
measured as described in 11.1.3; 
temperatures  of  ME EQUIPMENT  parts  that  are  not  APPLIED  PARTS but  are  likely  to  be 
touched,  exceeding  the  allowable  values  in  Table  23  when  measured  and  adjusted  as 
described in 11.1.3; 

– 

–  exceeding the allowable values for “other components and materials” identified in Table 22 
times 1,5 minus 12,5 °C. Limits for windings are found in Table 26, Table 27 and Table 31. 
In all other cases, the allowable values of Table 22 apply. 

Temperatures shall be measured using the method described in 11.1.3. 

The  SINGLE  FAULT  CONDITIONS  in  4.7,  8.1 b),  8.7.2  and  13.2.2,  with  regard  to  the  emission  of 
flames,  molten  metal  or  ignitable  substances,  shall  not  be  applied  to  parts  and  components 
where: 
–  The  construction  or  the  supply  circuit  limits  the  power  dissipation  in  SINGLE  FAULT 

CONDITION to less than 15 W or the energy dissipation to less than 900 J. 

"""

print(re.findall(regex, string, re.M))

输出

[('12.4.5.4', '其他生产诊断或治疗的 ME 设备 辐射 \n适用时,制造商应在 风险管理流程 与我相关的\n风险 产生诊断或治疗辐射的设备,但不包括 \n用于诊断 X 射线和放射治疗(参见 12.4.5.2 和 12.4.5.3)。 \n\n通过检查风险管理来检查合规性 FILE.\n\n', '', ''), ('12.4.6', '诊断或治疗声学 压力 \n适用时,制造商应在 风险管理过程与诊断相关的\n风险 或治疗声压。 \n\n合规性检查由 检查风险管理文件。\n\n', '', ''), ('13', '* 危险情况和故障情况\n\n', '', ''), ('13.1', '特定危险情况\n\n* 一般\n\n', '', ''), ('13.1.1', '当应用单一故障条件时 在 4.7 中描述并在 13.2 中列出,一次一个\n,无 13.1.2 至 13.1.4(含)中的危险情况 应发生在\nME设备中。\n\n任何一个故障 一次的组件,这可能导致危险情况,是 \n在 4.7 中描述。 \n\n* 排放、外壳变形或 超过最高温度 \n\n', '', ''), ('', '', '13.1.2', 'The 不会发生以下危险情况:\n– 排放 火焰、熔融金属、有毒或易燃物质 危险\n\n数量; \n\n– ENCLOSURES 变形为这样的 符合 15.3.1 的程度受损; \n– \n\n温度 应用部分的数量超过中确定的允许值 表 24 当\n按 11.1.3 中所述测量时; \n温度 ME 设备部件不是应用部件,但可能 被\n触摸,超过表23中的允许值 当按照 11.1.3 中的描述进行测量和调整时; \n\n– \n\n– 超过“其他组件和材料”的允许值 在表 22 中确定\n乘以 1.5 - 12.5 °C。绕组限制 见表 26、表 27 和表 31。\n在所有其他情况下, 表 22 的允许值适用。 \n\n温度应为 使用 11.1.3 中描述的方法测量。 \n\n单一故障 4.7、8.1 b)、8.7.2 和 13.2.2 中的条件,关于 \n火焰、熔融金属或可燃物质的排放, 不得应用于零件和组件\n其中:\n– 建设或供电电路限制了功率 在单一故障\n\n条件下耗散到小于 15 W 或 能量耗散至小于 900 J。\n\n')]

【讨论】:

  • 我最终能够重新创建与昨晚深夜相同的输出。你认为你能简单地解释你的正则表达式吗,因为我想我会接受你的回答……这似乎更符合我一直在寻找的东西。它需要一点调整,如果我能多理解一点,我想我可以自己做。谢谢!
【解决方案2】:

您可以使用您的模式并在其后匹配一个空格,然后是该行的其余部分。

然后重复匹配以下所有不以标题开头的行。

^\d+(?:\.\d+)* .*(?:\r?\n(?!\d+(?:\.\d+)* ).*)*
  • ^\d+(?:.\d+)* 匹配标题后跟空格的模式
  • .* 匹配除换行符以外的任何字符 0+ 次
  • (?:非捕获组
    • \r?\n 匹配换行符
    • (?!负前瞻,断言右边的不是
      • \d+(?:.\d+)* 标题模式
    • ) 关闭前瞻
    • .* 匹配除换行符以外的任何字符 0+ 次
  • )*关闭非捕获组并重复0+次以匹配所有行

Regex demo

【讨论】:

  • 那个正则表达式效果很好。它发现标题非常好!谢谢。当您说 “重复匹配以下所有不以标题开头的行”时,这是否意味着我添加到您提供的正则表达式或使用不同的正则表达式创建某种 if 语句?对不起,如果这是一个愚蠢的问题。
  • 这根本不是一个愚蠢的问题。该模式应首先匹配标题,然后是该行的其余部分。然后,当您希望在行尾继续匹配换行符和整个下一行时,只要不是以与标题匹配的模式开头。您不必在模式中添加任何内容,因为在匹配换行符(?!\d+(?:\.\d+)* 后,该部分由负前瞻处理
  • 好的,所以我的输出与正则表达式演示中的输出有很大不同。我不知道我在这里做错了什么。这是输出的链接:docdro.id/1hBvQXr 尽管我觉得答案很明显,但我仍在努力解决这个问题。感谢您的耐心等待
  • 您可以尝试读取整个文件,然后使用 findall,而不是逐行读取文件。
  • @wuddadid 虽然其他答案也可以,但您可以检查 regex101 演示链接的步骤数以比较两种模式的效率。
【解决方案3】:

感谢他们详细的回答和有用的解释,我最终将@The-fourth-bird 的部分代码和@Emma 的部分代码合并到这个正则表达式中,这似乎可以很好地满足我的需要。

(^\d+(?:\.\d+)*\s+)((?![a-z])[\s\S].*(?:\r?\n))([\s\S]*?)(?=^\d+(?:\.\d+)*\s+(?![a-z]))

这里是REGEX DEMO

我做我想做的事,将(数字标题)、(文字标题)和(正文)分成由逗号分隔的组,这允许我使用自定义分隔符将它们分成 Excel 中的列 ), ( 和其他一些后期处理。

这个新的正则表达式的好处是它跳过了只是参考而不是实际标题的编号标题,如下所示:

【讨论】:

  • 为什么不用regex101.com/r/034ARv/1 ^(\d+(?:\.\d+)*) (.*)((?:\r?\n(?!\d+(?:\.\d+)* ).*)*) 步骤更少。
  • 对于我列出的特定用例,这提供了最好的结果。
【解决方案4】:
import pdfplumber
import re
pdfToString = ""

with pdfplumber.open(r"sample.pdf") as pdf:
    for page in pdf.pages:
        print(page.extract_text())
        pdfToString += page.extract_text()

matches = re.findall(r'^\d+(?:\.\d+)* .*(?:\r?\n(?!\d+(?:\.\d+)* ).*)*',pdfToString, re.M)
for i in  matches:
    if "word_to_extract" in i[:50]:
        print(i)

此解决方案是提取问题中所有具有相同标题格式的标题,并提取所需的标题及其后面的段落。

【讨论】:

    猜你喜欢
    • 2017-10-08
    • 1970-01-01
    • 2015-04-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-18
    相关资源
    最近更新 更多