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]*\)).)(?=[^]*\)|(?<!\()(\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中的正则表达式嵌套括号的主要内容,如果未能解决你的问题,请参考以下文章