【问题标题】:Python partition string with regular expressions带有正则表达式的 Python 分区字符串
【发布时间】:2015-12-24 03:02:55
【问题描述】:

我正在尝试使用 Python 的分区和正则表达式来清理文本字符串。例如:

testString = 'Tre Bröders Väg 6 2tr'
sep = '[0-9]tr'
head,sep,tail = testString.partition(sep)
head
>>>'Tre Br\xc3\xb6ders V\xc3\xa4g 6 2tr'

头部仍然包含我要删除的 2tr。我不太擅长正则表达式,但 [0-9] 不应该这样做吗?

我希望从这个例子中得到的输出是

head
>>> 'Tre Br\xc3\xb6ders V\xc3\xa4g 6

【问题讨论】:

  • 你期望输出什么?
  • 你甚至没有在这里使用正则表达式,那为什么[0-9] 会这样做呢?
  • 添加了我期望的输出
  • @AshwiniChaudhary,为什么我不使用正则表达式?有什么特别需要我补充的吗?我正在使用这个备忘单:cheatography.com/davechild/cheat-sheets/regular-expressions
  • 你只想要头部?

标签: python regex partition


【解决方案1】:

str.partition 不支持 regex ,因此当您给它一个类似 - '[0-9]tr' 的字符串时,它会尝试在 testString 中找到确切的字符串以进行分区,它没有使用任何正则表达式。

根据documentation of str.partition -

在第一次出现 sep 时拆分字符串,并返回一个 3 元组,其中包含分隔符之前的部分、分隔符本身和分隔符之后的部分。如果没有找到分隔符,则返回一个包含字符串本身的 3 元组,后跟两个空字符串。

既然你说,你只想要 head ,你可以使用 re 模块中的 re.split() 方法,将 maxsplit 设置为 1 ,然后取它的第一个元素,这应该相当于什么您正在尝试使用str.partition。示例 -

import re
testString = 'Tre Bröders Väg 6 2tr'
sep = '[0-9]tr'
head = re.split(sep,testString,1)[0]

演示 -

>>> import re
>>> testString = 'Tre Bröders Väg 6 2tr'
>>> sep = '[0-9]tr'
>>> head = re.split(sep,testString,1)[0]
>>> head
'Tre Bröders Väg 6 '

【讨论】:

    【解决方案2】:

    对于那些仍在寻找如何进行正则表达式分区的答案的人,请尝试以下功能:

    import regex # re also works
    
    def regex_partition(content, separator):
        separator_match = regex.search(separator, content)
        if not separator_match:
            return content, '', ''
    
        matched_separator = separator_match.group(0)
        parts = regex.split(matched_separator, content, 1)
    
        return parts[0], matched_separator, parts[1]
    

    【讨论】:

      【解决方案3】:

      普通的re.split() 方法

      您可以使用re.split() 提取head

      import re
      
      testString = 'Tre Bröders Väg 6 2tr'
      sep = r'[0-9]tr'  # "r" is essential here!
      head, tail = re.split(sep, testString)  
      head.strip()
      >>>'Tre Bröders Väg 6'
      

      巧克力洒re.split()方法

      如果你用()捕获sepre.split()的行为就像一个伪re.partition()(在Python中没有这样的方法,实际上......)

      import re
      
      testString = 'Tre Bröders Väg 6 2tr'
      sep = r'([0-9]tr)'  # "()" added.
      # maxplit of 1 is added at the suggestion of Ángel ;)
      head, sep, tail = re.split(sep, testString, 1)
      head, sep, tail
      >>>('Tre Bröders Väg 6 ', '2tr', '')
      

      【讨论】:

      • A re.split containing a group 确实是创建正则表达式分区的方法,尽管要实际模拟分区,您应该添加 1 的 maxplit,即 re.split(sep, testString, 1)
      • 非常感谢天使。现在看起来好多了!
      【解决方案4】:

      我来到这里是为了寻找一种使用基于正则表达式的方法partition()

      正如yelichi answer中包含的那样,re.split()如果包含捕获组,则可以返回分隔符,因此基于正则表达式创建分区函数的最基本方法是:

      re.split( "(%s)" % sep, testString, 1)
      

      但是,这只适用于简单的正则表达式。如果您通过使用组的正则表达式进行拆分(即使没有捕获),它也不会提供预期的结果。

      我首先查看了skia.heliou answer 提供的函数,但它不必要地第二次运行正则表达式,更重要的是,如果模式与自身不匹配,则会失败(它应该在matched_separator 上使用string.split,而不是re.split。分裂)。

      因此我实现了我自己的支持正则表达式的 partition() 版本:

      def re_partition(pattern, string, return_match=False):
          '''Function akin to partition() but supporting a regex
          :param pattern: regex used to partition the content
          :param content: string being partitioned
          '''
      
          match = re.search(pattern, string)
      
          if not match:
              return string, '', ''
      
          return string[:match.start()], match if return_match else match.group(0), string[match.end():]
      
      

      作为一个附加功能,它可以返回匹配对象本身,而不仅仅是匹配的字符串。这使您可以直接与分隔符的组进行交互。

      并以迭代器形式:

      def re_partition_iter(pattern, string, return_match=False):
          '''Returns an iterator of re_partition() output'''
      
          pos = 0
          pattern = re.compile(pattern)
          while True:
              match = pattern.search(string, pos)
              if not match:
                  if pos < len(string):  # remove this line if you prefer to receive an empty string
                      yield string[pos:]
                  break
      
              yield string[pos:match.start()]
              yield match if return_match else match.group(0)
              pos = match.end()
      

      【讨论】:

        猜你喜欢
        • 2015-03-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-05-26
        • 2017-02-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多