【问题标题】:Using Regex to select specific section of a text使用正则表达式选择文本的特定部分
【发布时间】:2021-12-28 00:01:14
【问题描述】:

假设我有以下文件:

document1 = '1. Hello world\n1.1 bla bla bla\n1.2 more bla bla\n1.3 even more bla bla ABC\n\n2. ABC \n2.1 hello ABC\n2.2 bla bla bla\n\n3. XYZ\n3.1 bla bla\n3.2 more bla bla\n3.3 even more bla bla'

格式如下:

1. Hello world
1.1 bla bla bla
1.2 more bla bla
1.3 even more bla bla ABC

2. ABC 
2.1 hello ABC
2.2 bla bla bla

3. XYZ
3.1 bla bla
3.2 more bla bla
3.3 even more bla bla

我想知道如何选择ABC section only,这样我得到的输出为:

2. ABC 
2.1 hello ABC
2.2 bla bla bla

有人可能会建议使用re.findall(r'^2\..*', document1, re.MULTILINE),但注意 ABC section 并不总是必须在第 2 点。例如,我可以:

document2 = '1. Hello world\n1.1 bla bla bla\n1.2 more bla bla\n1.3 even more bla bla ABC\n\n2. XYZ\n2.1 bla bla\n2.2 more bla bla\n2.3 even more bla bla\n\n\n3. MNO\n 3.1 hello MNO\n3.2 bla bla bla\n\n\n4. ABC\n4.1 hello ABC\n4.2 bla bla bla'

1. Hello world
1.1 bla bla bla
1.2 more bla bla
1.3 even more bla bla ABC

2. XYZ
2.1 bla bla
2.2 more bla bla
2.3 even more bla bla

3. MNO 
3.1 hello MNO
3.2 bla bla bla

4. ABC 
4.1 hello ABC
4.2 bla bla bla

ABC 在第 4 节中。

【问题讨论】:

    标签: python regex string text


    【解决方案1】:

    你可以使用

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

    请参阅regex demo。仅在编译正则表达式对象时传递 re.M 标志。 详情

    • ^ - 行首
    • \d+ - 一位或多位数字
    • \. - 一个点
    • \s* - 零个或多个空格
    • ABC - ABC 字符串
    • [^\S\n]* - 零个或多个空格,而不是 LF 字符
    • (?:\n.+)* - 零个或多个非空行。

    要获取所有匹配项,您可以使用

    matches =  re.findall(r'^\d+\.\s*ABC[^\S\n]*(?:\n.+)*', document1, re.M)
    

    要获得第一场比赛只有你可以使用

    match = re.search(r'^\d+\.\s*ABC[^\S\n]*(?:\n.+)*', document1, re.M)
    if match:
        print(match.group())
    

    【讨论】:

      【解决方案2】:

      我会将文本分成几段:

      >>> document1.split("\n\n")
      [
        "1. Hello world\n1.1 bla bla bla\n1.2 more bla bla\n1.3 even more bla bla ABC",
        "2. ABC \n2.1 hello ABC\n2.2 bla bla bla",
        "3. XYZ\n3.1 bla bla\n3.2 more bla bla\n3.3 even more bla bla"
      ]
      
      >>> document2.split("\n\n")
      [
        "1. Hello world\n1.1 bla bla bla\n1.2 more bla bla\n1.3 even more bla bla ABC",
        "2. XYZ\n2.1 bla bla\n2.2 more bla bla\n2.3 even more bla bla",
        "\n3. MNO\n 3.1 hello MNO\n3.2 bla bla bla",
        "\n4. ABC\n4.1 hello ABC\n4.2 bla bla bla"
      ]
      

      然后搜索包含“.ABC”的段落:

      found = next((para for para in document1.split("\n\n") if ". ABC" in para), "")
      

      以上内容也适用于 document2。如果需要,可以将测试 ". ABC" in para 替换为 re.search(r"\d+\. ABC", para)

      【讨论】:

      • [para for para in re.split('\n{2,}', document2) if re.search(r'^.*ABC', para)] 请注意,他的示例在一个或两个实例中有两个以上 \n...
      【解决方案3】:

      这是获取它的一种方法,首先提取该部分的初始数字,然后应用您建议的 findall 方法。请注意,如果该部分出现多次,则需要调整代码。

      import re
      
      document1 = '1. Hello world\n1.1 bla bla bla\n1.2 more bla bla\n1.3 even more bla bla ABC\n\n2. ABC \n2.1 hello ABC\n2.2 bla bla bla\n\n3. XYZ\n3.1 bla bla\n3.2 more bla bla\n3.3 even more bla bla'
      document2 = '1. Hello world\n1.1 bla bla bla\n1.2 more bla bla\n1.3 even more bla bla ABC\n\n2. XYZ\n2.1 bla bla\n2.2 more bla bla\n2.3 even more bla bla\n\n\n3. MNO\n 3.1 hello MNO\n3.2 bla bla bla\n\n\n4. ABC\n4.1 hello ABC\n4.2 bla bla bla'
      
      def get_section(document, substr):
          section_expr = "\d*\. " + substr
          section_no = re.findall(section_expr, document)[0].rsplit('. ', 1)[0]
          subsection_expr = str(section_no) + '\..*'
          return re.findall(subsection_expr, document)
      
      print(get_section(document1, "ABC"))
      print(get_section(document2, "ABC"))
      

      结果:

      ['2. ABC ', '2.1 hello ABC', '2.2 bla bla bla']
      ['4. ABC', '4.1 hello ABC', '4.2 bla bla bla']
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-11-30
        • 2011-01-06
        • 2016-03-26
        • 2023-03-23
        • 2018-11-29
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多