正则表达式,多个括号和方括号

时间:2014-10-25 13:19:26

标签: python regex python-3.x parentheses square-bracket

来自@ avinash-raj的回答:

re.findall(r'\([^\[\]()]*\[\([^\[\]()]+source=([\w./]+)', s)

修改后的问题:

我有以下字符串:

s=string='s=<a=1 b=[(text1 [(text2 source=x.gz i=i.gz)]), ([(text3 j=1.0 source=y.gz)])] c=[([(3)])] d=[([(source=x.gz)])]>'

我希望将此列表作为输出:

['x.gz','y.gz']

原始问题:

我有以下字符串:

s=string='s=<a=1 b=[([(source=x.gz i=0)]), ([(j=1 source=y.gz)])] c=[([(3)])]>'

我希望将此列表作为输出:

['x.gz','y.gz']

我试过这个:

re.findall(r'b=\[([^]]*)\]',s)

返回:

['([(source=x.gz i=0)']

我也试过这个:

re.findall(r'\[([^]]*)\]',s)

返回:

['([(source=x.gz i=0)', '(j=1 source=y.gz)', '([(3)']

我对同一个答案或指向教程同样感到高兴,这使我能够在完成答案后自己找到答案。感谢。

EDIT1:更改了字符串(请参阅下面的答案):

s=string='s=<a=1 b=[([(source=x.gz i=0)]), ([(j=1 source=y.gz)])] c=[([(3)])] source=4>'

EDIT2:更改字符串(未提供答案,但我会自行提供):

s=string='s=<a=1 b=[(text1 [(text2 source=x.gz i=i.gz)]), ([(text3 j=1.0 source=y.gz)])] c=[([(3)])] d=[([(source=x.gz)])]>'

我试过了:

re.findall(r'(?<=b=)\[\(.*?[\S]*?source=([\w\./]+)', s)

但它只会返回:

['x.gz']

5 个答案:

答案 0 :(得分:4)

使用capturing groups捕获要打印的字符。

>>> string = 's=<a=1 b=[([(source=x.gz i=0)]), ([(j=1 source=y.gz)])] c=[([(3)])] source=4>'
>>> re.findall(r'\(\[\([^\[\]()]*source=([\w.]+)', string)
['x.gz', 'y.gz']

<强>解释

  • \(\[\(字面上匹配([(个字符。
  • [^\[\]()]*一个否定的字符类,匹配任何字符,但不匹配[]()零次或多次。
  • source=匹配字符串source=
  • ([\w.]+)一次或多次捕获单词字符或点。

<强>更新

>>> string = 's=<a=1 b=[(text1 [(text2 source=x.gz i=i.gz)]), ([(text3 j=1.0 source=y.gz)])] c=[([(3)])] d=[([(source=x.gz)])]>'
>>> re.findall(r'\([^\[\]()]*\[\([^\[\]()]+source=([\w.]+)', string)
['x.gz', 'y.gz']

答案 1 :(得分:3)

如果你只想要source值,也许你可以使用它:

>>> re.findall(r'source=([\w\.]+)', s)
['x.gz', 'y.gz']

此正则表达式指定应捕获source=之后显示的内容,只要它是句点.或字母数字字符。

修改:更新后的字符串:

>>> s = 's=<a=1 b=[([(source=x.gz i=0)]), ([(j=1 source=y.gz)])] c=[([(3)])] source=4>'
>>> re.findall(r'\[\([\w=\s]*source=([\w\.]+)', s)
['x.gz', 'y.gz']

现在正则表达式指定source=必须以[(开头,并且在[\w=\s]集(字母数字,=,空格)中包含零个或多个字符。

编辑2 :与上面几乎完全相同,只是[\w=\s]已扩展为包含.

>>> s = 's=<a=1 b=[(text1 [(text2 source=x.gz i=i.gz)]), ([(text3 j=1.0 source=y.gz)])] c=[([(3)])] d=[([(source=x.gz)])]>'
>>> re.findall(r'\[\([\w=\.\s]*source=([\w\.]+)', s)
['x.gz', 'y.gz', 'x.gz']

答案 2 :(得分:2)

这个正则表达式发现所有的来源=在肠胃外。

s='s=<a=1 b=[([(source=x.gz i=0)]), ([(j=1 source=y.gz)])] c=[([(3)])]>'
re.findall(r"source=(\S+?)(?:\s|[)])",s)
['x.gz', 'y.gz']

如果你只想要那些([(和)])

re.findall(r"[(]\[[(][\s\S]*?source=([\w\.]+)[\s\S]*?[)]\][)]",s)

我从大学开始就接受了正则表达式的攻击,但自从我开始阅读PERL regex guide后,我开始喜欢正则表达式。

答案 3 :(得分:0)

您可以使用the new regex module中的一个很好的功能,它允许从重复捕获组中提取所有结果。请注意,同一模块也允许使用重复的命名捕获。

示例:

import regex

s = 's=<a=1 b=[([(source=x.gz i=0)]), ([(j=1 source=y.gz)])] c=[([(3)])] source=4>'

# description of an element 
elt = r'''\( [^[]* \[\(
        (?>
            \b source=(?<source> [^\s)]+ )
          |
            [^s)]+
          |
            \Bs+
          |
            s(?!ource=)
        )*
        \)\]\)
'''
p = regex.compile(r'b=\[%s(?:,\ *%s)*' % (elt, elt), regex.VERBOSE);

m = p.search(s)

print(m.captures('source'))

结果:

['x.gz', 'y.gz']

这种方法的主要兴趣在于您可以处理未定义数量的元素,并确保这些元素来自您选择的值(a,b,c ...)。

请注意,对于这种方法,不再需要findall方法,因为重复在模式本身中,因此search方法就足够了。

答案 4 :(得分:0)

这也会产生结果:

re.findall(r'source=([a-z]+\.[a-z]+)',s,re.I)
['x.gz', 'y.gz']

适用于所有编辑。 re.I 设置不区分大小写的标记。