【问题标题】:How to split by commas that are not within parentheses?如何用不在括号内的逗号分隔?
【发布时间】:2021-03-19 05:33:44
【问题描述】:

假设我有一个这样的字符串,其中项目用逗号分隔,但在带有括号内容的项目中也可能有逗号:

(编辑:抱歉,忘记提及某些项目可能没有括号内容)

"Water, Titanium Dioxide (CI 77897), Black 2 (CI 77266), Iron Oxides (CI 77491, 77492, 77499), Ultramarines (CI 77007)"

如何仅用不在括号内的逗号分割字符串?即:

["Water", "Titanium Dioxide (CI 77897)", "Black 2 (CI 77266)", "Iron Oxides (CI 77491, 77492, 77499)", "Ultramarines (CI 77007)"]

我想我必须使用正则表达式,也许是这样的:

([(]?)(.*?)([)]?)(,|$)

但我仍在努力让它发挥作用。

【问题讨论】:

  • 你能展示一下你到目前为止所做的尝试吗?

标签: python regex


【解决方案1】:

使用negative lookahead 匹配所有不在括号内的逗号。根据匹配的逗号拆分输入字符串将为您提供所需的输出。

,\s*(?![^()]*\))

DEMO

>>> import re
>>> s = "Water, Titanium Dioxide (CI 77897), Black 2 (CI 77266), Iron Oxides (CI 77491, 77492, 77499), Ultramarines (CI 77007)"
>>> re.split(r',\s*(?![^()]*\))', s)
['Water', 'Titanium Dioxide (CI 77897)', 'Black 2 (CI 77266)', 'Iron Oxides (CI 77491, 77492, 77499)', 'Ultramarines (CI 77007)']

【讨论】:

  • regex101.com 再次来袭! :)(一个小时前我也刚刚评论了here
  • 我有类似的问题,但这对我不起作用,因为有内括号。例如,“水、二氧化钛 (CI 77897)、黑色 2 (CI 77266)、氧化铁 (CI 77491、77492(w)、77499)、群青 (CI 77007)”
  • 这不适用于匹配括号但是,试试这个:s="b.buildPlanPHID,coalesce(concat('D', r.Id), concat('D',c.revisionID), concat('D', d.revisionID)) as revision_id ,d.Id as diff_id" 应该将它分成 3 个标记,但它会创建更多。
  • 是的,这不适用于包含超过 1 级括号的字符串。
  • 搜索了一段时间,这是唯一对我有用的正则表达式解决方案
【解决方案2】:

您只需使用str.replacestr.split 即可。 您可以使用任何字符替换),

a = "Titanium Dioxide (CI 77897), Black 2 (CI 77266), Iron Oxides (CI 77491, 77492, 77499), Ultramarines (CI 77007)"
a = a.replace('),', ')//').split('//')
print a

输出:-

['Titanium Dioxide (CI 77897)', ' Black 2 (CI 77266)', ' Iron Oxides (CI 77491, 77492, 77499)', ' Ultramarines (CI 77007)']

【讨论】:

  • 字符串water在哪里?
  • @AvinashRaj 哦!我只是在我的字符串中错过了它。
  • 此解决方案不会拆分不以括号结尾的项目(如示例中的Water),因此字符串拆分不正确。
【解决方案3】:

我相信我有一个更简单的正则表达式:

rx_comma = re.compile(r",(?![^(]*\))")
result = rx_comma.split(string_to_split)

正则表达式的解释:

  • 匹配,
  • NOT 后跟:
    • ) 结尾的字符列表,其中:
    • ,) 之间的字符列表不包含 (

它在嵌套括号的情况下不起作用,例如a,b(c,d(e,f))。如果需要这个,一种可能的解决方案是通过拆分结果,如果字符串具有开放括号而没有关闭,请进行合并:),例如:

"a"
"b(c" <- no closing, merge this 
"d(e" <- no closing, merge this
"f))

【讨论】:

    【解决方案4】:

    这个版本似乎可以使用嵌套括号、方括号([] 或 )和大括号:

    def split_top(string, splitter, openers="([{<", closers = ")]}>", whitespace=" \n\t"):
        ''' Splits strings at occurance of 'splitter' but only if not enclosed by brackets.
            Removes all whitespace immediately after each splitter.
            This assumes brackets, braces, and parens are properly matched - may fail otherwise '''
    
    outlist = []
    outstring = []
    
    depth = 0
    
    for c in string:
        if c in openers:
            depth += 1
        elif c in closers:
            depth -= 1
    
            if depth < 0:
                raise SyntaxError()
    
        if not depth and c == splitter:
            outlist.append("".join(outstring))
            outstring = []
        else:
            if len(outstring):
                outstring.append(c)
            elif c not in whitespace:
                outstring.append(c)
    
    outlist.append("".join(outstring))
    
    return outlist
    

    像这样使用它:

    s = "Water, Titanium Dioxide (CI 77897), Black 2 (CI 77266), Iron Oxides (CI 77491, 77492, 77499), Ultramarines (CI 77007)"
    
    split = split_top(s, ",") # splits on commas
    

    我知道,这可能不是有史以来最快的。

    【讨论】:

      【解决方案5】:

      试试正则表达式

      [^()]*\([^()]*\),?
      

      代码:

      >>x="Titanium Dioxide (CI 77897), Black 2 (CI 77266), Iron Oxides (CI 77491, 77492, 77499), Ultramarines (CI 77007)"
      >> re.findall("[^()]*\([^()]*\),?",x)
      ['Titanium Dioxide (CI 77897),', ' Black 2 (CI 77266),', ' Iron Oxides (CI 77491, 77492, 77499),', ' Ultramarines (CI 77007)']
      

      查看正则表达式的工作原理http://regex101.com/r/pS9oV3/1

      【讨论】:

        【解决方案6】:

        使用regex,这可以通过findall 函数轻松完成。

        import re
        s = "Titanium Dioxide (CI 77897), Black 2 (CI 77266), Iron Oxides (CI 77491, 77492, 77499), Ultramarines (CI 77007)"
        re.findall(r"\w.*?\(.*?\)", s) # returns what you want
        

        如果您想更好地理解正则表达式,请使用http://www.regexr.com/,这里是 python 文档的链接:https://docs.python.org/2/library/re.html

        编辑: 我修改了正则表达式字符串以接受不带括号的内容:\w[^,(]*(?:\(.*?\))?

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-06-01
          • 1970-01-01
          • 1970-01-01
          • 2016-04-12
          • 2017-04-02
          • 2022-01-03
          • 1970-01-01
          • 2019-08-19
          相关资源
          最近更新 更多