【问题标题】:Regular Expression conflict due to user inputs由于用户输入导致的正则表达式冲突
【发布时间】:2015-02-07 14:35:27
【问题描述】:

我想根据正则表达式将字符串分成 2 组。该字符串基本上具有以下结构:

some text (data1 | data2 | data3 | data4)

我使用了一个简单的正则表达式如下:

re.match("^(?P<title>.*)\((?P<data>.*)\)$", s)

只要字符串中没有括号,它就可以正常工作,这会与正则表达式冲突。

但如果其中一组中有括号,则会输出意外结果:

>>> import re
>>> def process_string1(s):
...    r = re.match("^(?P<title>.*?)\((?P<data>.*)\)$", s)
...    return r.groups()
...
>>> def process_string2(s):
...    r = re.match("^(?P<title>.*)\((?P<data>.*)\)$", s)
...    return r.groups()
...
>>> s = "this is an example (detail) (data1 | data2 | data3 | data4)"
>>> print process_string1(s)
('this is an example ', 'detail) (data1 | data2 | data3 | data4')      # Wrong
>>> print process_string2(s)
('this is an example (detail) ', 'data1 | data2 | data3 | data4')      # Good
>>> s = "this is another example (data1 (detail) | data2 | data3 | data4)"
>>> print process_string1(s)
('this is another example ', 'data1 (detail) | data2 | data3 | data4') # Good
>>> print process_string2(s)
('this is another example (data1 ', 'detail) | data2 | data3 | data4') # Wrong

你能帮帮我吗?

【问题讨论】:

  • Python 正则表达式默认是“贪婪”的。他们抓取满足表达式的最长字符串。如果字符串中有其他 '(',第一部分将抓取 '('。也许你应该将 '.*' 更改为 '[^(]*'?

标签: python regex


【解决方案1】:

查看这些答案:

简而言之,正则表达式不是像您一样匹配递归/嵌套结构的工具。您要求正则表达式匹配:

something (something (someting) something)

这是递归的,因为最里面的something 可能再次是something (something) something。正则表达式不适用于此工具,您应该为此使用parser。有关详细信息,请参阅以下问题:

【讨论】:

    【解决方案2】:

    许多正则表达式支持递归或嵌套结构。 Python 的引擎目前不支持它,但正在开发一个替换模块,它确实支持递归:

    https://pypi.python.org/pypi/regex

    【讨论】:

      【解决方案3】:

      我终于把我的代码改成了如下:

      >>> import re
      >>> def process_string(s):
      ...    r = re.match("^(?P<title>.*)\((?P<data>.*)\)$", s)    
      ...    if '(' in r.group('title') and not ')' in r.group('title'):
      ...        r = re.match("^(?P<title>.*?)\((?P<data>.*)\)$", s)
      ...    return r.groups()
      

      这会产生我期望的结果:

      >>> print process_string("this is an example (detail) (data1 | data2 | data3 | data4)")
      ('this is an example (detail) ', 'data1 | data2 | data3 | data4')
      
      >>> print process_string("this is an example (data1 (detail) | data2 | data3 | data4)")
      ('this is an example ', 'data1 (detail) | data2 | data3 | data4')
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-07-20
        • 1970-01-01
        • 1970-01-01
        • 2012-09-10
        相关资源
        最近更新 更多