【问题标题】:Regex divide with upper-case正则表达式除以大写
【发布时间】:2011-01-17 10:11:04
【问题描述】:

我想用正则表达式替换 'HDMWhoSomeThing''HDM Who Some Thing' 这样的字符串。

所以我想提取以大写字母开头或仅由大写字母组成的单词。请注意,在字符串 'HDMWho' 中,最后一个大写字母实际上是单词 Who 的第一个字母 - 不应包含在单词 HDM 中。

实现此目标的正确正则表达式是什么?我尝试了许多类似于[A-Z][a-z]+ 的正则表达式,但没有成功。 [A-Z][a-z]+ 给了我'Who Some Thing' - 当然没有'HDM'

有什么想法吗? 谢谢, 鲁基

【问题讨论】:

    标签: python regex string split uppercase


    【解决方案1】:
    #! /usr/bin/env python
    
    import re
    from collections import deque
    
    pattern = r'([A-Z]{2,}(?=[A-Z]|$)|[A-Z](?=[a-z]|$))'
    chunks = deque(re.split(pattern, 'HDMWhoSomeMONKEYThingXYZ'))
    
    result = []
    while len(chunks):
      buf = chunks.popleft()
      if len(buf) == 0:
        continue
      if re.match(r'^[A-Z]$', buf) and len(chunks):
        buf += chunks.popleft()
      result.append(buf)
    
    print ' '.join(result)
    

    输出:

    HDM Who Some MONKEY Thing XYZ

    从代码行来看,这个任务更适合re.findall

    pattern = r'([A-Z]{2,}(?=[A-Z]|$)|[A-Z][a-z]*)'
    print ' '.join(re.findall(pattern, 'HDMWhoSomeMONKEYThingX'))
    

    输出:

    HDM Who Some MONKEY Thing X

    【讨论】:

    • 我认为这个也遇到了字符串中间全大写单词的问题。对字符串 'HDMWhoSomeMONKEYThing' 调用的 re.split 将为您提供 [HDM, Who, SomeMONKEY, Thing]
    【解决方案2】:

    可能是'[A-Z]*?[A-Z][a-z]+'?

    编辑:这似乎有效:[A-Z]{2,}(?![a-z])|[A-Z][a-z]+

    import re
    
    def find_stuff(str):
      p = re.compile(r'[A-Z]{2,}(?![a-z])|[A-Z][a-z]+')
      m = p.findall(str)
      result = ''
      for x in m:
        result += x + ' '
      print result
    
    find_stuff('HDMWhoSomeThing')
    find_stuff('SomeHDMWhoThing')
    

    打印出来:

    HDM 谁的东西

    一些 HDM 人物

    【讨论】:

    • 几乎正确 - 但它给出的是“HDMWho Some Thing”而不是“HDM Who Some Thing”
    • 我的确切代码:str = 'HDMWhoSomeThing'\np = re.compile('[AZ]*?[AZ][az]+')\nm = p.findall('HDMWhoSomeThing') \n result = ''\n for x in m:\n result += x + ' '\n print result\n 我用 \n 更改了行尾
    • 在字符串中的任何位置遗漏了一个单字符的大写单词:'HDMWhoSomeAThingA' 将不匹配任何一个 'A'(将 {2,} 更改为 +,它将获取单字符单词)
    【解决方案3】:

    一个班轮:

    ' '.join(a or b for a,b in re.findall('([AZ][az]+)|(?:([AZ]*)(?=[AZ]))', s))

    使用正则表达式

    ([A-Z][a-z]+)|(?:([A-Z]*)(?=[A-Z]))

    【讨论】:

    • 这不会匹配字符串末尾的单字符大写单词。 OP 在它们之间插入空格的应用程序无关紧要,但如果需要对所有单词进行其他操作,则可能会出现问题。
    【解决方案4】:

    所以在这种情况下,“单词”是:

    1. 任意数量的大写字母 - 除非最后一个大写字母后跟一个小写字母。
    2. 一个大写字母后跟任意数量的小写字母。

    那就试试吧:

    ([A-Z]+(?![a-z])|[A-Z][a-z]*)

    第一个替代包括一个否定前瞻 (?![a-z]),它处理全大写单词和初始大写单词之间的边界。

    【讨论】:

      【解决方案5】:

      尝试用这个正则表达式分割:

      /(?=[A-Z][a-z])/
      

      如果您的正则表达式引擎不支持拆分空匹配项,请尝试使用此正则表达式在单词之间放置空格:

      /([A-Z])(?![A-Z])/
      

      将其替换为" $1"(第一组的空格加匹配)。然后你就可以在空格处拆分了。

      【讨论】:

      • 我正在使用 Python。不幸的是,模式 (?=[A-Z][a-z]) 不匹配,模式 ([A-Z])(?![A-Z]) 给出 "W S T" :(
      • @Rukki Odds:我写过你必须用空格替换 ([A-Z])(?![A-Z]) 的匹配项,然后是第一组的匹配项以分隔单词。然后你可以使用\s+来拆分单词。
      • ([A-Z])(?![A-Z]) 如果字符串中间有一个全大写的单词将无济于事:例如,'HDMWhoSomeMONKEYThing' 将仅匹配 'Who'、'Some 中的 W、S 和 T '和'事物'
      猜你喜欢
      • 2011-02-01
      • 1970-01-01
      • 2019-01-13
      • 1970-01-01
      • 2014-05-12
      • 1970-01-01
      • 2013-07-25
      • 2017-01-23
      • 2023-03-11
      相关资源
      最近更新 更多