首页 文章

是否有正则表达式来检测有效的正则表达式?

提问于
浏览
639

是否可以使用另一个正则表达式检测有效的正则表达式?如果是,请在下面给出示例代码 .

7 回答

  • 150
    /
    ^                                             # start of string
    (                                             # first group start
      (?:
        (?:[^?+*{}()[\]\\|]+                      # literals and ^, $
         | \\.                                    # escaped characters
         | \[ (?: \^?\\. | \^[^\\] | [^\\^] )     # character classes
              (?: [^\]\\]+ | \\. )* \]
         | \( (?:\?[:=!]|\?<[=!]|\?>)? (?1)?? \)  # parenthesis, with recursive content
         | \(\? (?:R|[+-]?\d+) \)                 # recursive matching
         )
        (?: (?:[?+*]|\{\d+(?:,\d*)?\}) [?+]? )?   # quantifiers
      | \|                                        # alternative
      )*                                          # repeat content
    )                                             # end first group
    $                                             # end of string
    /
    

    这是一个递归正则表达式,许多正则表达式引擎都不支持 . 基于PCRE的应该支持它 .

    没有空格和评论:

    /^((?:(?:[^?+*{}()[\]\\|]+|\\.|\[(?:\^?\\.|\^[^\\]|[^\\^])(?:[^\]\\]+|\\.)*\]|\((?:\?[:=!]|\?<[=!]|\?>)?(?1)??\)|\(\?(?:R|[+-]?\d+)\))(?:(?:[?+*]|\{\d+(?:,\d*)?\})[?+]?)?|\|)*)$/
    

    .NET不直接支持递归 . ( (?1)(?R) 构造 . )递归必须转换为计数 balancer 组:

    ^                                         # start of string
    (?:
      (?: [^?+*{}()[\]\\|]+                   # literals and ^, $
       | \\.                                  # escaped characters
       | \[ (?: \^?\\. | \^[^\\] | [^\\^] )   # character classes
            (?: [^\]\\]+ | \\. )* \]
       | \( (?:\?[:=!]
             | \?<[=!]
             | \?>
             | \?<[^\W\d]\w*>
             | \?'[^\W\d]\w*'
             )?                               # opening of group
         (?<N>)                               #   increment counter
       | \)                                   # closing of group
         (?<-N>)                              #   decrement counter
       )
      (?: (?:[?+*]|\{\d+(?:,\d*)?\}) [?+]? )? # quantifiers
    | \|                                      # alternative
    )*                                        # repeat content
    $                                         # end of string
    (?(N)(?!))                                # fail if counter is non-zero.
    

    压实:

    ^(?:(?:[^?+*{}()[\]\\|]+|\\.|\[(?:\^?\\.|\^[^\\]|[^\\^])(?:[^\]\\]+|\\.)*\]|\((?:\?[:=!]|\?<[=!]|\?>|\?<[^\W\d]\w*>|\?'[^\W\d]\w*')?(?<N>)|\)(?<-N>))(?:(?:[?+*]|\{\d+(?:,\d*)?\})[?+]?)?|\|)*$(?(N)(?!))
    
  • 7

    好问题 . 真正的常规语言无法决定任意深度嵌套的良好形式的括号 . 即,如果您的字母包含'('和')',那么目标是确定这些字符串是否具有格式良好的匹配括号 . 由于这是正则表达式的必要条件,因此答案是否定的 .

    但是:如果放宽要求并添加递归,则可以执行此操作 . 原因是递归可以充当“堆栈”,让您通过推入此堆栈来“计算”当前的嵌套深度 .

    Russ Cox撰写了关于正则表达式引擎实现的精彩论文:Regular Expression Matching Can Be Simple And Fast

  • 4

    虽然完全有可能像MizardX发布的那样使用递归正则表达式,但对于这类事情来说,解析器更有用 . Regexes最初打算用于常规语言,递归或 balancer 组只是一个补丁 .

    定义有效正则表达式的语言实际上是一个无上下文语法,您应该使用适当的解析器来处理它 . 这是一个用于解析简单正则表达式的大学项目的示例(没有大多数构造) . 它使用JavaCC . 是的,评论是西班牙语,虽然方法名称是不言自明的 .

    SKIP :
    {
        " "
    |   "\r"
    |   "\t"
    |   "\n"
    }
    TOKEN : 
    {
        < DIGITO: ["0" - "9"] >
    |   < MAYUSCULA: ["A" - "Z"] >
    |   < MINUSCULA: ["a" - "z"] >
    |   < LAMBDA: "LAMBDA" >
    |   < VACIO: "VACIO" >
    }
    
    IRegularExpression Expression() :
    {
        IRegularExpression r; 
    }
    {
        r=Alternation() { return r; }
    }
    
    // Matchea disyunciones: ER | ER
    IRegularExpression Alternation() :
    {
        IRegularExpression r1 = null, r2 = null; 
    }
    {
        r1=Concatenation() ( "|" r2=Alternation() )?
        { 
            if (r2 == null) {
                return r1;
            } else {
                return createAlternation(r1,r2);
            } 
        }
    }
    
    // Matchea concatenaciones: ER.ER
    IRegularExpression Concatenation() :
    {
        IRegularExpression r1 = null, r2 = null; 
    }
    {
        r1=Repetition() ( "." r2=Repetition() { r1 = createConcatenation(r1,r2); } )*
        { return r1; }
    }
    
    // Matchea repeticiones: ER*
    IRegularExpression Repetition() :
    {
        IRegularExpression r; 
    }
    {
        r=Atom() ( "*" { r = createRepetition(r); } )*
        { return r; }
    }
    
    // Matchea regex atomicas: (ER), Terminal, Vacio, Lambda
    IRegularExpression Atom() :
    {
        String t;
        IRegularExpression r;
    }
    {
        ( "(" r=Expression() ")" {return r;}) 
        | t=Terminal() { return createTerminal(t); }
        | <LAMBDA> { return createLambda(); }
        | <VACIO> { return createEmpty(); }
    }
    
    // Matchea un terminal (digito o minuscula) y devuelve su valor
    String Terminal() :
    {
        Token t;
    }
    {
        ( t=<DIGITO> | t=<MINUSCULA> ) { return t.image; }
    }
    
  • 225

    你可以将正则表达式提交给preg_match,如果正则表达式无效,它将返回false . 不要忘记使用'@'来禁止错误消息:

    @preg_match($regexToTest, '');
    

    如果正则表达式是'//',则

    • 将返回1 .
      如果正则表达式正常,
    • 将返回0 .
      否则
    • 将返回false .
  • 6

    如果您严格地谈论正则表达式而不包括一些实际上是无上下文语法的正则表达式实现,请不 .

    正则表达式有一个限制,这使得无法编写匹配所有正则表达式的正则表达式 . 您无法匹配配对的大括号等实现 . 正则表达式使用许多这样的结构,让我们以[]为例 . 只要有[必须有匹配] . 足够简单的正则表达式“[ . *]” .

    正则表达式无法实现的原因是它们可以嵌套 . 你怎么写一个匹配嵌套括号的正则表达式?答案是你不能没有无限长的正则表达式 . 你可以通过暴力匹配任意数量的嵌套parens,但你不能匹配任意长的嵌套括号 .

    此功能通常称为计数(您计算嵌套的深度) . 根据定义,正则表达式无法计算 .

    编辑:结束撰写关于此的博客文章:Regular Expression Limitations

  • 639

    不太可能 .

    try..catch 或您提供的任何语言中评估它 .

  • 36

    为了返回匹配字符串集,在pyparsing wiki上的这个example给出了解析一些正则表达式的语法 . 因此,它拒绝了那些重新回归的问题 .

相关问题