python中的正则表达式嵌套括号

Posted

技术标签:

【中文标题】python中的正则表达式嵌套括号【英文标题】:Regex nested parenthesis in python 【发布时间】:2013-06-14 09:12:30 【问题描述】:

我有这样的事情:

Othername California (2000) (T) (S) (ok) state (#2.1)

是否有正则表达式代码获取:

Othername California ok 2.1

即我想将数字保留在圆括号内,而圆括号又在 内,并将文本“ok”保留在 () 内。 如果包含在我的行中,我特别需要打印字符串“ok”,但我想去掉括号内的其他文本,例如 (V)、(S) 或 (2002)。

我知道正则表达式可能不是处理此类问题的最有效方法。

任何帮助将不胜感激。

编辑:

字符串可能会有所不同,因为如果某些信息不可用,则不包含在该行中。文本本身也是可变的(例如,我没有每一行的“状态”)。所以可以有例如:

Name1 Name2 Name3 (2000) (ok) edu (#1.1)
Name1 Name2 (2002) edu (#1.1)
Name1 Name2 Name3 (2000) (V) variation (#4.12)

【问题讨论】:

数据的顺序是否严格? (例如:“Something state (year) (.) (.) (ok?) state (#number)”?在这种情况下,我认为您需要使用拆分功能:pythonforbeginners.com/python-strings/python-split 不,实际上可能因行而异,仅在可用时才包含信息 必须转义正则表达式字符。字符 () 必须转义为:“\” 例如:\。在 url 中测试:gskinner.com/RegExr 真正的挑战是在这里匹配2.1,如果我们想考虑它的多个实例,例如state (#2.1) yellow (33),这将非常困难。这种情况的问题在于:你“理论上”有两种方法可以解决它:1)如果有,则向前看和向后看,问题是必须向后看大多数正则表达式风格中的固定长度(python 相同)2) 使用子组匹配,例如\(?:.*?\((\w+)\).*?)+\,这在大多数正则表达式风格中不可用。因此,我认为纯正则表达式功能是不可能完成您的任务的。 您能否发布更多可能输入的示例?目前尚不清楚字符串的哪些部分保持不变,哪些部分可能会有所不同。 【参考方案1】:

正则表达式

(.+)\s+\(\d+\).+?(?:\(([^)]2,)\)\s+(?=))?\.+\(#(\d+\.\d+)\)\

用于测试的文本

Name1 Name2 Name3 (2000) 教育 (#3.2) Name1 Name2 Name3 (2000) (ok) edu (#1.1) 姓名 1 姓名 2 (2002) edu (#1.1) Name1 Name2 Name3 (2000) (V) 变体 (#4.12) 别名加利福尼亚 (2000) (T) (S) (ok) state (#2.1)

测试

>>> 正则表达式 = re.compile("(.+)\s+\(\d+\).+?(?:\(([^)]2,)\)\s+(?=)) ?\.+\(#(\d+\.\d+)\)\") >>> r = 正则表达式。搜索(字符串) >>> r <_sre.sre_match> >>> 正则表达式匹配(字符串) <_sre.sre_match> # 运行 findall >>> 正则表达式.findall(字符串) [ (u'Name1 Name2 Name3' , u'' , u'3.2'), (u'Name1 Name2 Name3' , u'ok', u'1.1'), (u'Name1 Name2' , u'' , u'1.1'), (u'Name1 Name2 Name3' , u'' , u'4.12'), (u'Othername California', u'ok', u'2.1') ]

【讨论】:

酷。您是如何生成正则表达式图的? 不幸的是,它不适用于我的所有文本行并给出错误。我想问题在于文本刺痛一直在变化。例如。可能有其他词代替“状态”,也可能有多个词代替它。唯一的循环模式由括号的存在给出 @phimuemue 我使用了debuggex.com。网站上有一个选项可以在 SO 上嵌入任何正则表达式。 @user2447387 所以尝试用.+替换stats\s+ 我不知道为什么,但是用我数据库中的另一行测试它不起作用:“Name1 Name2 Name3 (2000) Education (#3.2)”。它给了我“AttributeError:'NoneType'对象没有属性'groups'”。不幸的是,如果信息不可用,有时信息不会出现在行中【参考方案2】:

试试这个:

import re

thestr = 'Othername California (2000) (T) (S) (ok) state (#2.1)'

regex = r'''
    ([^(]*)             # match anything but a (
    \                   # a space
    (?:                 # non capturing parentheses
        \([^(]*\)       # parentheses
        \               # a space
    )3                # three times
    \(([^(]*)\)         # capture fourth parentheses contents
    \                   # a space
                       # opening 
        [^]*           # anything but 
        \(\#            # opening ( followed by #
            ([^)]*)     # match anything but )
        \)              # closing )
                       # closing 
'''

match = re.match(regex, thestr, re.X)

print match.groups()

输出:

('Othername California', 'ok', '2.1')

这是压缩版:

import re

thestr = 'Othername California (2000) (T) (S) (ok) state (#2.1)'
regex = r'([^(]*) (?:\([^(]*\) )3\(([^(]*)\) [^]*\(\#([^)]*)\)'
match = re.match(regex, thestr)

print match.groups()

【讨论】:

【参考方案3】:

尽管我在 cmets 中说过。我找到了解决办法:

(?(?=\([^()\w]*[\w.]+[^()\w]*\))\([^()\w]*([\w.]+)[^()\w]*\)|.)(?=[^]*\)|(?<!\()(\b\w+\b)(?!\()|ok

说明:

(?                                  # If
(?=\([^()\w]*[\w.]+[^()\w]*\))      # There is (anything except [()\w] zero or more times, followed by [\w.] one or more times, followed by anything except [()\w] zero or more times)
\([^()\w]*([\w.]+)[^()\w]*\)        # Then match it, and put [\w.] in a group
|                                   # else
.                                   # advance with one character
)                                   # End if
(?=[^]*\)                         # Look ahead if there is anything except  zero or more times followed by 

|                                   # Or
(?<!\()(\b\w+\b)(?!\()              # Match a word not enclosed between parenthesis
|                                   # Or
ok                                  # Match ok

Online demo

【讨论】:

对不起,如果我问(我是 python 和一般编码的新手)..你能给我一些其他几行来测试这个(我试过 re.sub 但它给我一个错误。谢谢! 我尝试在 re.sub 和第一个答案代码中替换您的正则表达式,但它给了我一个错误...让我再试一下... python好像不支持这种if/else语句,试试(?:(?=\([^()\w]*[\w.]+[^()\w]*\))\([^()\w]*([\w.]+)[^()\w]*\)|(?!\([^()\w]*[\w.]+[^()\w]*\)).)(?=[^]*\)|(?&lt;!\()(\b\w+\b)(?!\()|ok 这次没有错误,但我得到了错误的输出。使用 "Name1 Name2 Name3 (2000) (V) variation (#4.12)" 作为字符串,我得到: "Name1 Name2 Name3 (2000) (V) " @user2447387 我赞成您的问题,以便您获得 20 个代表,您现在可以在 python chatroom 寻求帮助。【参考方案4】:

其他情况是:

^(\w+\s?\w+)\s?\(\d1,\)\s?\(\w+\)\s?\(\w+\)\s?\((\w+)\)\s?.*#(\d.\d)

【讨论】:

以上是关于python中的正则表达式嵌套括号的主要内容,如果未能解决你的问题,请参考以下文章

删除(嵌套)括号的正则表达式

使用正则表达式在嵌套括号外查找匹配项

由于未知错误,嵌套括号的动态正则表达式失败

js 正则表达式获取小括号内的内容,不含括号

用正则表达式解析布尔算术,包括括号?

用于匹配嵌套括号内的特定文本的 C# 正则表达式