【问题标题】:python regular expression replace two situations with one commandpython正则表达式用一个命令替换两种情况
【发布时间】:2015-03-27 12:10:45
【问题描述】:

我想替换像

这样的字符串
'''1  2  3  4  5  6 abcde fghij klmno pqrst 7 8 9 10 uvwxyz abcdef 11 12 13'''

'''1  2  3  4  5  6
abcde fghij klmno pqrst
7 8 9 10
uvwxyz abcdef
11 12 13'''

这是我的方法:

s = re.sub(r'(\d) ([a-z])', r'\1\n\2', s)
s = re.sub(r'([a-z]) (\d)', r'\1\n\2', s)

如何在one regular expression 中做到这一点?我知道我可以使用re.findallgroups 来做到这一点,但我想找到更简单的方法?

【问题讨论】:

    标签: python regex replace


    【解决方案1】:

    我真的认为最简单的方法是使用findall 匹配而不是拆分或sub-ing:

    result = re.findall(r"\d+(?:\s+\d+)*|[a-z]+(?:\s+[a-z]+)*", text)
    print('\n'.join(result))
    

    或一行:

    result = '\n'.join(re.findall(r"\d+(?:\s+\d+)*|[a-z]+(?:\s+[a-z]+)*", text))
    

    给予:

    1  2  3  4  5  6
    abcde fghij klmno pqrst
    7 8 9 10
    uvwxyz abcdef
    11 12 13
    

    \d+(?:\s+\d+)* 匹配带有数字和空格的部分。

    [a-z]+(?:\s+[a-z]+)* 匹配有字母和空格的部分。

    【讨论】:

    • 这只是给了我另一种解决问题的方法,很棒而且简洁。
    • 你可能想做 [a-z]+(?:\s+[a-z]+)* 来匹配字母和空格
    • @XWen 对了,把代码移到这里是有遗漏的,很好 :)
    【解决方案2】:

    这里有两种使用单个正则表达式的方法:

    • 使用条件模式。捕获\1 很简单。捕获\4 会检查我们是否抓取了\2\3,然后相应地定义其余的模式。

      re.sub(r'((\d)|([a-z])) ((?(2)[a-z]|\d))', r'\1\n\4', s)
      
    • 只替换空格,并用look-behind和look-ahead断言包围它。

      re.sub(r'(?<=\d) (?=[a-z])|(?<=[a-z]) (?=\d)', '\n', s)
      

    但是你的两个简单的正则表达式比所有这些废话都要好。

    【讨论】:

    • @GuidoBouman 也许您应该知道,使用条件和/或环视比不使用它们需要更多的时间和资源!不过,在小范围内肯定可以忽略不计。
    • @Jerry 感谢您的关注。我发现前瞻和后置方法更好,因为您只更换您实际需要更换的部分。这使您的代码不易出错。
    【解决方案3】:

    你可以使用正则表达式或命令:

    s = re.sub(r'((\d) ([a-z])|([a-z]) (\d))', r'\2\4\n\3\5', s)
    

    它将匹配第 2 组和第 3 组或第 4 组和第 5 组。=]

    【讨论】:

    • 我在运行您的代码时得到这个:error: unmatched group.
    • 哎呀,你用的是哪个版本的 Python?最近已修复此问题:hg.python.org/cpython/rev/bd2f1ea04025
    • @GuidoBouman 但它不适用于 Python 2.7,谢谢大家。
    • 没问题,其他解决方案显然更适合您的情况。 =]
    【解决方案4】:

    你可以使用re.split

    >>> s = '''1  2  3  4  5  6 abcde fghij klmno pqrst 7 8 9 10 uvwxyz abcdef 11 12 13'''
    >>> for i in re.split(r'(?<=\d)\s+(?=[A-Za-z])|(?<=[A-Za-z])\s+(?=\d)', s):
            print(i)
    
    
    1  2  3  4  5  6
    abcde fghij klmno pqrst
    7 8 9 10
    uvwxyz abcdef
    11 12 13
    >>> print('\n'.join(re.split(r'(?<=\d)\s+(?=[A-Za-z])|(?<=[A-Za-z])\s+(?=\d)', s)))
    

    re.sub

    >>> print(re.sub(r'(?<=\d)\s+(?=[A-Za-z])|(?<=[A-Za-z])\s+(?=\d)', r'\n', s))
    1  2  3  4  5  6
    abcde fghij klmno pqrst
    7 8 9 10
    uvwxyz abcdef
    11 12 13
    

    上面的re.sub 命令会用换行符替换数字和字母之间或字母和数字之间的一个或多个空格。

    【讨论】:

      【解决方案5】:

      您可以使用替代品:

      re.sub(r'(\d[\d\s]*|[a-z][a-z\s]*)', r'\1\n', s)
      

      要对尾随空格更加严格,您可以这样做:

      re.sub(r'(\d(?:[\d\s]*\d)?|[a-z](?:[a-z\s]*[a-z])?)\s*', r'\1\n', s).rstrip()
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-04-29
        • 2012-02-16
        • 2021-07-13
        相关资源
        最近更新 更多