正则表达式:带可选部分的字符串

时间:2012-01-26 13:39:46

标签: python regex

我正在尝试解析一些文档字符串。

示例文档字符串是:

Test if a column field is larger than a given value
    This function can also be called as an operator using the '>' syntax

    Arguments:
        - DbColumn self
        - string or float value: the value to compare to
            in case of string: lexicographic comparison
            in case of float: numeric comparison
    Returns:
        DbWhere object

ArgumentsReturns部分都是可选的。我希望我的正则表达式以组的形式返回描述(第一行),Arguments部分(如果存在)和Returns部分(如果存在)。

我现在的正则表达式是:

m = re.search('(.*)(Arguments:.*)(Returns:.*)', s, re.DOTALL)

并在以下所有三个部分都存在的情况下工作,但只要ArgumentsReturns部分不可用就会失败。我已尝试使用非贪婪修饰符(如??)进行多种修改,但无济于事。

修改:当ArgumentsReturns部分存在时,我实际上只想匹配Arguments:Returns:之后的文字分别

谢谢!

2 个答案:

答案 0 :(得分:9)

尝试:

re.search('^(.*?)(Arguments:.*?)?(Returns:.*)?$', s, re.DOTALL)

只需通过附加?制作第二组和第三组可选,并通过(再次)制作前两组非贪婪的限定符在?上添加.*(是的,令人困惑)。

此外,如果在模式的第一组上使用非贪婪修饰符,它将匹配最短的子字符串,$为空字符串。您可以通过在模式的末尾添加行尾字符(Arguments)来克服这个问题,这会强制第一个组匹配尽可能少的字符以满足模式,即整个字符串何时出现没有Returns和没有Arguments:部分,以及这些部分之前的所有部分(如果存在)。

编辑:好的,如果您只想在 Returns:<?P<name>令牌之后捕获文本,那么您将不得不掖好在几个小组中。我们不打算使用所有组,因此用>>> m = re.search('^(?P<description>.*?)(Arguments:(?P<arguments>.*?))?(Returns:(?P<returns>.*))?$', s, re.DOTALL) >>> m.groupdict()['description'] "Test if a column field is larger than a given value\n This function can also be called as an operator using the '>' syntax\n\n " >>> m.groupdict()['arguments'] '\n - DbColumn self\n - string or float value: the value to compare to\n in case of string: lexicographic comparison\n in case of float: numeric comparison\n ' >>> m.groupdict()['returns'] '\n DbWhere object' >>> 符号(另一个问号,argh!)命名它们 - 开始有意义了:

{{1}}

答案 1 :(得分:3)

如果您想在可选的Arguments:Returns:部分 AND 之后匹配文字,则不希望使用(?P<name>...)命名您的捕获组,您也可以使用(?:...)非常规括号的捕获版本。

正则表达式看起来像这样:

m = re.search('^(.*?)(?:Arguments:(.*?))?(?:Returns:(.*?))?$', doc, re.DOTALL)
#                     ^^                  ^^

根据Python3 documentation

  

(?:...)

     

常规括号的非捕获版本。匹配括号内的正则表达式,但在执行匹配后或在模式中稍后引用时,无法检索组匹配的子字符串。