正则表达式匹配

gau*_*rav 4 regex

我想写一个匹配任何东西的正则表达式

()
(())
(()())
((()))
()()()
Run Code Online (Sandbox Code Playgroud)

等等

tch*_*ist 21

所有这些答案声称你不能使用模式来匹配具有平衡嵌套parens的字符串是非常错误的.假装现代编程语言匹配的模式仅限于病理教科书意义上的"常规语言"是不切实际的.一旦你允许反向引用,它们就不会.这使得真实世界的模式比教科书版本更匹配,使它们更加实用.

匹配平衡parens的最简单模式是\((?:[^()]*+|(?0))*\).但是你永远不应该这样写,因为它太紧凑而不易读.您应该始终使用/x模式编写它以允许空格和注释.所以这样写:

m{
  \(              # literal open paren
     (?:          # begin alternation group
         [^()]*+  #  match nonparens possessively
       |          # or else
         (?0)     #  recursively match entire pattern
     )*           # repeat alternation group
  \)              # literal close paren
}x
Run Code Online (Sandbox Code Playgroud)

对于命名抽象,并将它们的定义及其排序与执行分离,还有很多要说的.这导致了这种情况:

my $nested_paren_rx = qr{

    (?&nested_parens)

    (?(DEFINE)

        (?<open>       \(       )
        (?<close>       \)      )
        (?<nonparens> [^()]     )

        (?<nested_parens>
            (?&open)
            (?:
                (?&nonparens) *+
              |
                (?&nested_parens)
            ) *
            (?&close)
        )

    )
}x;
Run Code Online (Sandbox Code Playgroud)

第二种形式现在可以包含在更大的模式中.

不要让任何人告诉你不能使用模式来匹配递归定义的东西.正如我刚才所说,你当然可以.

当你在它的时候,确保永远不要写线噪声模式.你不必,你不应该.没有编程语言可以维护,禁止使用空格,注释,子例程或字母数字标识符.所以在你的模式中使用所有这些东西.

当然,它确实有助于为这种工作选择正确的语言.☺


Mar*_*mic 5

如果您遇到正则表达式语法不支持递归匹配的语言,我会给您简单的Javascript实现,您应该可以使用您选择的语言创建自己的语言:

function testBraces(s) {
    for (var i=0, j=0; i<s.length && j>=0; i++)
        switch(s.charAt(i)) {
            case '(': { j++ ; break; }
            case ')': { j-- ; break; }
        }

    return j == 0;
}
Run Code Online (Sandbox Code Playgroud)

在这里你可以玩它:http://jsfiddle.net/BFsn2/

  • 我不知道一些正则表达式的味道会进行递归模式匹配,因为在我使用的语言中,它们没有.大部分时间(阅读:关于我的雇主项目)我不会选择与我合作的语言.我修好了答案. (3认同)