Regex validando regex [cerrado]


17

Cree una expresión regular que acepte una cadena de expresión regular como entrada y verifique si es válida. Básicamente, su expresión regular debería poder validarse. (Cualquier expresión regular no válida no debe validarse, por lo que no puede usarla .*.)

Su sabor debe ser totalmente compatible con implementaciones bien conocidas (Perl, sed, grep, gawk, etc.), y debe ser totalmente compatible con lo que esas implementaciones admiten. [No te preocupes por el abogado habla; Solo estoy tratando de eliminar cualquier posible escapatoria para los *** inteligentes.]


Lo , pero me preocupa que les dé una ventaja a aquellos que conocen y usan sabores no ricos en características. ¿O son mis preocupaciones infundadas?


8
no es posible, los corchetes de anidación arbitrarios hacen que una expresión regular sea una gramática libre de contexto, (reemplazarla con una notación polaca también necesita una pila)
monstruo de trinquete

@ratchet Augh, puede que tengas razón.
Mateen Ulhaq

1
existen algunas extensiones en los idiomas regulares que pueden permitir coincidir con los corchetes, pero no sé cómo hacerlo
Ratchet freak

8
Seguro que será posible con expresiones regulares de Perl.
Peter Taylor

1
Las expresiones regulares de @BrianVandenberg implementadas en los idiomas modernos son prácticamente no regulares ... tan pronto como agregue referencias, puede hacer coincidir los idiomas no regulares. Además, tanto Perl / PCRE como .NET son lo suficientemente potentes como para coincidir con la anidación correcta.
Martin Ender

Respuestas:


22

Rubí

Traté de hacer coincidir la sintaxis real del sabor de la expresión regular de Ruby tanto como sea posible, pero hay algunas peculiaridades: acepta algunos aspectos retrospectivos que en realidad no son válidos (como (?<=(?<!))) y reconoce rangos de caracteres vacíos como D-A. Este último podría repararse para ASCII, pero la expresión regular es lo suficientemente larga como es.

\A(?<main>
    (?!
        \{(\d+)?,(\d+)?\} # do not match lone counted repetition
    )
    (?:
        [^()\[\]\\*+?|<'] | # anything but metacharacters
        (?<cclass>
            \[ \^? (?: # character class
                (?: # character class
                    [^\[\]\\-] | # anything but square brackets,  backslashes or dashes
                    \g<esc> |
                    \[ : \^? (?: # POSIX char-class
                        alnum | alpha | word | blank | cntrl | x?digit | graph | lower | print | punct | space | upper
                    ) : \] |
                    - (?!
                        \\[dwhsDWHS]
                    ) # range / dash not succeeded by a character class
                )+ |
                \g<cclass> # more than one bracket as delimiter
            ) \]
        ) |
        (?<esc>
            \\[^cuxkg] | # any escaped character
            \\x \h\h? | # hex escape
            \\u \h{4} | # Unicode escape
            \\c . # control escape
        ) |
        \\[kg] (?:
            < \w[^>]* (?: > | \Z) |
            ' \w[^']* (?: ' | \Z)
        )? | # named backrefs
        (?<! (?<! \\) \\[kg]) [<'] | # don't match < or ' if preceded by \k or \g
        \| (?! \g<rep> ) | # alternation
        \( (?: # group
            (?:
                \?
                (?:
                    [>:=!] | # atomic / non-capturing / lookahead
                    (?<namedg>
                        < [_a-zA-Z][^>]* > |
                        ' [_a-zA-Z][^']* ' # named group
                    ) |
                    [xmi-]+: # regex options
                )
            )?
            \g<main>*
        ) \) |
        \(\?<[!=] (?<lbpat>
            (?! \{(\d+)?,(\d+)?\} )
            [^()\[\]\\*+?] |
            \g<esc>  (?<! \\[zZ]) |
            \g<cclass> |
            \( (?: # group
                (?:
                    \?: |
                    \? \g<namedg> |
                    \? <[!=]
                )?
                \g<lbpat>*
            ) \) |
            \(\?\# [^)]* \)
        )* \)
        |
        \(\? [xmi-]+ \) # option group
        (?! \g<rep> ) 
        |
        \(\?\# [^)]*+ \) # comment
        (?! \g<rep> )
    )+
    (?<rep>
        (?:
            [*+?] | # repetition
            \{(\d+)?,(\d+)?\} # counted repetition
        )
        [+?]? # with a possessive/lazy modifier
    )?
)*\Z

Versión ilegible:

\A(?<main>(?!\{(\d+)?,(\d+)?\})(?:[^()\[\]\\*+?|<']|(?<cclass>\[\^?(?:(?:[^\[\]\\-]|\g<esc>|\[:\^?(?:alnum|alpha|word|blank|cntrl|x?digit|graph|lower|print|punct|space|upper):\]|-(?!\\[dwhsDWHS]))+|\g<cclass>)\])|(?<esc>\\[^cuxkg]|\\x\h\h?|\\u\h{4}|\\c.)|\\[kg](?:<\w[^>]*(?:>|\Z)|'\w[^']*(?:'|\Z))?|(?<!(?<!\\)\\[kg])[<']|\|(?!\g<rep>)|\((?:(?:\?(?:[>:=!]|(?<namedg><[_a-zA-Z][^>]*>|'[_a-zA-Z][^']*')|[xmi-]+:))?\g<main>*)\)|\(\?<[!=](?<lbpat>(?!\{(\d+)?,(\d+)?\})[^()\[\]\\*+?]|\g<esc>(?<!\\[zZ])|\g<cclass>|\((?:(?:\?:|\?\g<namedg>|\?<[!=])?\g<lbpat>*)\)|\(\?#[^)]*\))*\)|\(\?[xmi-]+\)(?!\g<rep>)|\(\?#[^)]*+\)(?!\g<rep>))+(?<rep>(?:[*+?]|\{(\d+)?,(\d+)?\})[+?]?)?)*\Z

28
¿No son ambos la versión ilegible?
Kibbee

2
@Kibbee El primero es razonablemente legible si conoce bien la expresión regular.
Lowjacker

1
¿Cómo se asegura esto de que no hay referencias numéricas inválidas?
Martin Ender

1
Supongo que no. Por otra parte, no es la única limitación que tiene (ver arriba). Algunas cosas podrían arreglarse, pero la expresión regular se volvería ridículamente larga.
Lowjacker
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.