Regex memvalidasi regex [ditutup]

17

Buat regex yang akan menerima string regex sebagai input dan periksa apakah itu valid. Pada dasarnya, regex Anda harus dapat memvalidasi sendiri. (Regex yang tidak valid tidak boleh divalidasi, jadi Anda tidak dapat menggunakan .*.;))

Cita rasa Anda harus didukung sepenuhnya oleh implementasi yang terkenal (Perl, sed, grep, gawk, dll), dan itu harus sepenuhnya mendukung apa yang didukung oleh implementasi tersebut. [Jangan khawatir tentang pengacara yang berbicara; Aku hanya berusaha menghilangkan celah yang mungkin ada untuk para pelacur pintar.]


Saya akan itu, tapi saya khawatir itu akan memberi tepi bagi mereka yang tahu dan menggunakan rasa kaya fitur. Atau apakah kekhawatiran saya tidak berdasar?

Mateen Ulhaq
sumber
8
tidak mungkin, tanda kurung bersarang sembarang membuat regex konteks bebas tata bahasa, (menggantinya dengan notasi semir juga membutuhkan tumpukan)
ratchet freak
@ratchet Augh, Anda mungkin benar.
Mateen Ulhaq
1
beberapa ekstensi pada bahasa reguler ada yang memungkinkan pencocokan tanda kurung tapi saya tidak tahu bagaimana melakukannya
ratchet freak
8
Ini pasti dimungkinkan dengan Perl regex.
Peter Taylor
1
@BrianVandenberg ekspresi reguler yang diimplementasikan dalam bahasa modern hampir semuanya non-reguler ... segera setelah Anda menambahkan referensi, Anda dapat mencocokkan bahasa non-reguler. Selain itu, baik Perl / PCRE dan .NET cukup kuat untuk mencocokkan sarang yang benar.
Martin Ender

Jawaban:

22

Rubi

Saya mencoba mencocokkan sintaks sebenarnya dari rasa regex Ruby sebanyak mungkin, tetapi ada beberapa kebiasaan: ia menerima beberapa tampilan yang sebenarnya tidak valid (seperti (?<=(?<!))), dan mengenali rentang karakter kosong seperti D-A. Yang terakhir bisa diperbaiki untuk ASCII, tetapi regex sudah cukup lama.

\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 tidak terbaca:

\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
Lowjacker
sumber
28
Bukankah keduanya versi yang tidak dapat dibaca?
Kibbee
2
@ Kibbee Yang pertama cukup mudah dibaca jika Anda tahu regex dengan baik.
Lowjacker
1
Bagaimana cara memastikan bahwa tidak ada referensi numerik yang tidak valid?
Martin Ender
1
Saya kira tidak. Dan lagi, itu bukan satu-satunya batasan yang dimilikinya (lihat di atas). Beberapa hal bisa diperbaiki, tetapi regex akan menjadi sangat panjang.
Lowjacker