正则表达式中的贪婪可选字符

时间:2015-03-04 20:18:09

标签: regex

我有两个问题。

  1. 如何使可选字符变得贪婪?我试着写自定义 解析器并希望函数参数在括号中。对于 示例sin x变为sin(x)cosh^2 x变为cosh^2(x)。我的 正则表达式:

    input = 'sinh x'
    output=re.sub(r'(sin|cos|tan|cot|sec|csc)(h?)\s*(|\^\s*[\(]?\s*\-?\s*\d+\s*[\)]?\s*)?([a-z0-9]+)',r'\1\2\3(\4)', input)
    

    这很好用。但是当我输入sinh(x)时 (已经是格式良好的表达式),它输出sin(h)(x)。我需要 如果\ 4中没有匹配,则make(h?)贪婪或失败。怎么做?请注意,我无法写([a-gi-z0-9]),因为sinh(h)有效。

  2. (h?)([h]?)之间有什么区别吗?

3 个答案:

答案 0 :(得分:1)

不要让可选的h贪婪,而是考虑通过要求括号内的字母以空格或左括号作为前缀来消除你的语法:

  ((?<=\s|\()[a-z0-9]+)
// ^^^^^^^^^^^^

此lookbehind确保在没有空格的函数名称后面跟'h'(或任何其他字母)作为函数参数处理。

我会改变整体表达式如下:

((?:sin|cos|tan|cot|sec|csc)(?:h)?)\s*(?:[\^](\d+)\s*)?(?:((?<=\s|\()[a-z0-9]+)|[(]((?<=\s|\()[a-z0-9]+)[)])

^之后添加一个可选数字,并确保括号匹配(即两个括号都存在,或两个括号都丢失)。

Demo (using Java regex engine)

答案 1 :(得分:1)

  1. 可选字符已经贪婪(您可以使用??使其非贪婪)。但贪婪只是意味着它将尝试找到仍然允许正则表达式的其余部分匹配的最长匹配。如有必要,它仍会回溯。如果您想要强制失败,如果有其他事情,那么一种方法是使用negative lookahead。我发布了上述解释的价值。这是一个使用它的正则表达式:

    (sin|cos|tan|cot|sec|csc)(?!.\([^)]*\))(h?)\s*(|\^\s*[\(]?\s*\-?\s*\d+\s*[\)]?\s*)?([a-z0-9]+)
    
  2. DEMO

    1. 其中包含单个字符的字符类与直接将该字符放入RE中相同。之后的量词和围绕它的捕捉团队没有任何区别。有时,单字符类可用作转义的替代方法,例如, [*]?可能比\*?更容易阅读。

答案 2 :(得分:0)

这似乎是一种非常强大的方法来将输入解析为(function)(可能^ 2)(参数)

(sinh?|cosh?|tan|cot|sec|csc)[ (]*([\^a-z0-9]*?) *([a-z0-9]+)\)?$
更简单&amp;更简洁,也许使用前瞻方法。