正则表达式在python中括号内的所有字符周围添加空格

时间:2018-02-18 04:56:53

标签: python regex

我的目标是在parenthess之间分隔短划线。例如:"先生。女王(The-American-Detective,EQ),Holmes先生(The-British-Detective)"

我希望结果是

"先生。女王(The - American - Detective,EQ),Holmes先生(英国 - 侦探)"

我的代码是

re.sub(r'(.*)(\(.*)(-)(.*\))(.*)', r'\1\2 \3 \4\5', String)

但是,此代码似乎只分隔最后一个短划线出现在字符串的最后一个括号中。

它给出了结果"'先生。女王(The-America-Detective,EQ),Holmes先生(The-British-Detective)"

任何人都可以帮忙吗?我试图通过这里找到;但似乎我的代码应该按照我预期的方式工作

3 个答案:

答案 0 :(得分:3)

此代码的工作原理是将您的任务分为两部分。

  1. 在字符串target中搜索(...)
  2. 所包含的部分
  3. 然后使用https://github.com/angular/angularfire2/blob/master/docs/rtdb/querying-lists.md
  4. 在每个找到的-中搜索并替换每个(SPACE)-(SPACE) (...)

    代码:

    def expand_dashes(target):
        """
        replace all "-" with " - " when they are within ()
    
        target [string] - the original string
    
        return [string] - the replaced string
    
        * note, this function does not work with nested ()
        """
        return re.sub(r'(?<=\()(.*?)(?=\))', __helper_func, target)
    
    def __helper_func(match):
        """
        a helper function meant to process individual groups
        """
        return match.group(0).replace('-', ' - ')
    
    >>> x = "Mr. Queen (The-American-Detective, EQ), Mr. Holmes (The-British-Detective)"
    >>> expand_dashes(x)
    >>> "Mr. Queen (The - American - Detective, EQ), Mr. Holmes (The - British - Detective)"
    

答案 1 :(得分:1)

大多数正则表达式实现中的许多说明符(包括Python&#39;)贪婪地 < - >,也就是说,它们匹配尽可能多的输入字符串。因此,正则表达式中的第一个.*匹配所有输入字符串,除了最后一组括号 - 首先.*&#34;吃掉&#34;它仍然可以留下足够的剩余让整个正则表达式成功匹配。一旦进入那组括号,你首先得到另一个.*,它同样匹配它所能做的一切,并且仍然有其余的正则表达式足以成功匹配 - 所以除了的最后一对括号中的所有破折号最后一个破折号。因此,替换只在最后一组括号中的最后一个短划线周围插入空格,因为你的正则表达式只有一个非重叠的匹配:它匹配整个输入字符串,它只是正则表达式的一部分单挑括号中间只包括最后的短划线。

要解决此问题,您可能需要重新评估部分方法,因为re.sub将取代非重叠的匹配,而且很难(我怀疑它甚至可以构造一个单一的正则表达式,它可以匹配给定的一对圆括号之间的任意数量的短划线,并且相应的替换在每个这样的短划线周围放置空格,并且仍然使每个匹配不重叠(使用可以使用任意数组捕获的正则表达式系统,但据我所知,Python的实现仅捕获任何可重复组((<group>)*(<group>)+等)的最后捕获组。使用正则表达式检查破折号周围的括号是否需要将它们包含在匹配中,这意味着匹配并执行替换单个破折号的正则表达式将具有重叠匹配,其中有多个破折号一对括号。

增量方法虽然实现起来有点复杂,但可能是获得所需行为的更好方法。您可以将re.split与适当的正则表达式一起使用,将字符串拆分为带括号的部分和插入的非括号部分,然后使用更简单的正则表达式r'([^-]*)(-)([^-]*)'仅对括号部分执行正则表达式替换以匹配任何破折号*,然后用新的括号部分重新组装完整的序列。这有效地打破了单独捕获括号内的所有破折号。问题对于单个正则表达式来说有点难以将捕获权转化为两个问题,即找到带括号的部分&#39;并且&#39;单独捕捉破折号,这是更容易解决的问题。

*请注意,此正则表达式建议使用字符类[^-],表示任何不是-&#39;的字符。这可以避免您当前的.*正则表达式显示的问题,包括匹配内容的短划线和&#34;吃掉&#34;除了最后一个之外的所有,因为[^-]*在下一个字符是-时被迫停止匹配。在当前的正则表达式中简单地用.*替换[^-]*并不能解决问题,因为re.sub不会替换重叠的匹配,例如在这种情况下,相同的括号。

答案 2 :(得分:0)

尝试更简单方式:

import re
s = "Mr. Queen (The-American-Detective, EQ), Mr. Holmes (The-British-Detective) "
s = re.sub(r'(\w+)(\-)(\w+)(\-)(\w+)', '\\1 \\2 \\3 \\4 \\5', s)
print(s)

输出:

Mr. Queen (The - American - Detective, EQ), Mr. Holmes (The - British - Detective)

以下是正常工作

  • \w基本上与匹配的[a-zA-Z0-9_]相同 小写,大写,数字或下划线。

  • \-匹配-

因此,此正则表达式匹配something-anything-anotherthing形式的任何字符串,并将其替换为something - anything - anotherthing