【问题标题】:Extract substrings separately from a string using python regex使用 python 正则表达式从字符串中单独提取子字符串
【发布时间】:2019-01-04 08:30:39
【问题描述】:

我正在尝试编写一个正则表达式,它返回字符串之后的子字符串的一部分。例如:我想获取部分子字符串以及“15/08/2017”之后的空格。

a='''S
LINC             SHORT LEGAL                                   TITLE NUMBER
0037 471 661     1720278;16;21                                 172 211 342

LEGAL DESCRIPTION
PLAN 1720278  
BLOCK 16  
LOT 21  
EXCEPTING THEREOUT ALL MINES AND MINERALS  

ESTATE: FEE SIMPLE  
ATS REFERENCE: 4;24;54;2;SW

MUNICIPALITY: CITY OF EDMONTON

REFERENCE NUMBER: 172 023 641 +71

---------------------------------------------------------------------------- 
----
             REGISTERED OWNER(S)
REGISTRATION    DATE(DMY)  DOCUMENT TYPE      VALUE           CONSIDERATION
--------------------------------------------------------------------------- 
-- 
---

172 211 342    15/08/2017  AFFIDAVIT OF                       CASH & MTGE'''

有没有办法将'AFFIDAVIT OF''CASH & MTGE' 作为单独的字符串?

这是我到目前为止拼凑的表达方式:

doc = (a.split('15/08/2017', 1)[1]).strip()
'AFFIDAVIT OF                       CASH & MTGE'

【问题讨论】:

  • 我已经用实际输入的字符串进行了编辑。
  • 使用正则表达式可以吗?
  • 为什么要使用正则表达式?您愿意接受任何其他解决方案吗?
  • 是的,如果有比正则表达式更好的方法

标签: python regex python-3.x


【解决方案1】:

不是基于正则表达式的解决方案。但确实有效。

a='''S
LINC             SHORT LEGAL                                   TITLE NUMBER
0037 471 661     1720278;16;21                                 172 211 342

LEGAL DESCRIPTION
PLAN 1720278  
BLOCK 16  
LOT 21  
EXCEPTING THEREOUT ALL MINES AND MINERALS  

ESTATE: FEE SIMPLE  
ATS REFERENCE: 4;24;54;2;SW

MUNICIPALITY: CITY OF EDMONTON

REFERENCE NUMBER: 172 023 641 +71

---------------------------------------------------------------------------- 
----
            REGISTERED OWNER(S)
REGISTRATION    DATE(DMY)  DOCUMENT TYPE      VALUE           CONSIDERATION
--------------------------------------------------------------------------- 
-- 
---

172 211 342    15/08/2017  AFFIDAVIT OF                       CASH & MTGE'''

doc = (a.split('15/08/2017', 1)[1]).strip() 
# used split with two white spaces instead of one to get the desired result
print(doc.split("  ")[0].strip()) # outputs AFFIDAVIT OF
print(doc.split("  ")[-1].strip()) # outputs CASH & MTGE

希望对您有所帮助。

【讨论】:

    【解决方案2】:

    re 基于代码 sn-p

    import re
    foo = '''S
    LINC             SHORT LEGAL                                   TITLE NUMBER
    0037 471 661     1720278;16;21                                 172 211 342
    
    LEGAL DESCRIPTION
    PLAN 1720278
    BLOCK 16
    LOT 21
    EXCEPTING THEREOUT ALL MINES AND MINERALS
    
    ESTATE: FEE SIMPLE
    ATS REFERENCE: 4;24;54;2;SW
    
    MUNICIPALITY: CITY OF EDMONTON
    
    REFERENCE NUMBER: 172 023 641 +71
    
    ----------------------------------------------------------------------------
    ----
                 REGISTERED OWNER(S)
    REGISTRATION    DATE(DMY)  DOCUMENT TYPE      VALUE           CONSIDERATION
    ---------------------------------------------------------------------------
    --
    ---
    
    172 211 342    15/08/2017  AFFIDAVIT OF                       CASH & MTGE'''
    
    pattern = '.*\d{2}/\d{2}/\d{4}\s+(\w+\s+\w+)\s+(\w+\s+.*\s+\w+)'
    result = re.findall(pattern, foo, re.MULTILINE)
    print "1st match: ", result[0][0]
    print "2nd match: ", result[0][1]
    

    输出

    1st match:  AFFIDAVIT OF
    2nd match:  CASH & MTGE
    

    【讨论】:

      【解决方案3】:

      我们可以尝试将re.findall 与以下模式一起使用:

      PHASED OF ((?!\bCONDOMINIUM PLAN).)*)(?=CONDOMINIUM PLAN)
      

      在多行和 DOTALL 模式下搜索,上述模式将匹配出现在 PHASED OF 之间的所有内容,直到但不包括 CONDOMINIUM PLAN

      input = "182 246 612    01/10/2018  PHASED OF                           CASH & MTGE\n        CONDOMINIUM PLAN"
      result = re.findall(r'PHASED OF (((?!\bCONDOMINIUM PLAN).)*)(?=CONDOMINIUM PLAN)', input, re.DOTALL|re.MULTILINE)
      output = result[0][0].strip()
      print(output)
      
      CASH & MTGE
      

      请注意,我还从匹配项中删除了空格。我们也许可以修改正则表达式模式来做到这一点,但在一般的解决方案中,也许您希望在某些情况下保留一些空白。

      【讨论】:

      • 问题是 DOCUMENT TYPE 下面的字符串可能是多行的,不一定是多行的。如果是多行的话,应该考虑一下。
      • 我的回答涵盖了多行情况。如果您在我的回答中发现缺陷,请准确说明它是什么。
      • 我不知道这是怎么回事 result = re.findall(r'PHASED OF (((?!\bCONDOMINIUM PLAN).)*)(?=CONDOMINIUM PLAN)', input, re. DOTALL|re.MULTILINE)。我们不能把“公寓计划的阶段”作为一个词吗?
      • 不,我们不能,因此我最初在您的问题下评论说没有答案。您需要跨行匹配。
      • 好的,如果 date 之后没有多行单词,需要做什么修改?
      【解决方案4】:

      Why regular expressions?

      看起来您知道确切的分隔字符串,只需 str.split() 并获取第一部分:

      In [1]: a='172 211 342    15/08/2017  TRANSFER OF LAND   $610,000        CASH & MTGE'
      
      In [2]: a.split("15/08/2017", 1)[0]
      Out[2]: '172 211 342    '
      

      【讨论】:

      • 它不适用于我现在编辑的输入字符串
      • @Farook 在这种状态下不会,对。您可以调整解决方案并先将其拆分为换行符,但在这种情况下,正则表达式将能够一次性完成。
      【解决方案5】:

      我会避免在这里使用正则表达式,因为逻辑术语之间唯一有意义的分隔似乎是 2 个或更多空格。个别术语,包括您要匹配的术语,也可能有空格。因此,我建议使用\s{2,} 作为模式对输入进行正则表达式拆分。这些将产生一个包含所有术语的列表。然后,我们可以只在列表中走一遍,当我们找到前瞻词时,我们可以返回列表中的前一个词。

      import re
      a = "172 211 342    15/08/2017  TRANSFER OF LAND   $610,000        CASH & MTGE"
      parts = re.compile("\s{2,}").split(a)
      print(parts)
      
      for i in range(1, len(parts)):
          if (parts[i] == "15/08/2017"):
              print(parts[i-1])
      
      ['172 211 342', '15/08/2017', 'TRANSFER OF LAND', '$610,000', 'CASH & MTGE']
      172 211 342
      

      【讨论】:

        【解决方案6】:

        positive lookbehind assertion**

         m=re.search('(?<=15/08/2017).*', a)
         m.group(0)
        

        【讨论】:

          【解决方案7】:

          你必须返回正确的组:

          re.match("(.*?)15/08/2017",a).group(1)
          

          【讨论】:

            【解决方案8】:

            你需要使用 group(1)

            import re
            re.match("(.*?)15/08/2017",a).group(1)
            

            输出

            '172 211 342    '
            

            【讨论】:

              【解决方案9】:

              根据你的表达,我认为这是你需要的:

              import re
              
              a='172 211 342    15/08/2017  TRANSFER OF LAND   $610,000        CASH & MTGE'
              re.match("(.*?)(\w+/)",a).group(1)
              

              输出:

              '172 211 342    '
              

              【讨论】:

                【解决方案10】:

                你可以使用group(1)来做到这一点

                re.match("(.*?)15/08/2017",a).group(1)
                

                更新

                对于更新的字符串,您可以使用.search 而不是.match

                re.search("(.*?)15\/08\/2017",a).group(1)
                

                【讨论】:

                • 如果15/08/2017 之前有多个词,这将给出不正确的结果。
                • 我已经编辑了我的输入字符串。它不适用于现在正在编辑的字符串
                • 如果所需的术语不是第一个术语,这将完全失败。
                【解决方案11】:

                您的问题是您的字符串按原样格式化。 您正在寻找的线路是

                182 246 612 01/10/2018 PHASED OF CASH &amp; MTGE

                然后您正在寻找“PHASED OF”和一些空格之后的内容。

                你要搜索

                (?

                在你的字符串中。这将返回一个匹配对象,其中包含您在组 value 中查找的值。

                m = re.search(r'(?<=PHASED OF)\s*(?P<your_text>.*?)\n', a)
                your_desired_text = m.group('your_text')
                

                另外:有许多优秀的在线正则表达式测试人员可以摆弄您的正则表达式。 并且只有在完成正则表达式后,才将其复制并粘贴到 python 中。

                我用这个:https://regex101.com/

                【讨论】:

                • 我不是在搜索“PHASED OF”和一些空格之后的内容。相反,我在 DPCUMENT TYPE(即)'PHASED OF CONDOMINIUM PLAN' 下面的整个单词之后搜索字符串
                • “我需要在‘PHASED OF CONDOMINIUM PLAN’这个词之后获取字符串,它应该返回‘CASH & MTGE’,我已经尝试使用下面的表达式”。我哪里做错了?
                猜你喜欢
                • 2010-10-14
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多