Regex xác nhận regex [đã đóng]


17

Xây dựng một regex sẽ chấp nhận một chuỗi regex làm đầu vào và kiểm tra xem nó có hợp lệ không. Về cơ bản, regex của bạn sẽ có thể xác nhận chính nó. (Bất kỳ regex không hợp lệ nào sẽ không được xác thực, vì vậy bạn không thể sử dụng .*.;))

Hương vị của bạn phải được hỗ trợ đầy đủ bởi các triển khai nổi tiếng (Perl, sed, grep, gawk, v.v.) và nó phải hỗ trợ đầy đủ những gì các triển khai đó hỗ trợ. [Đừng lo lắng về luật sư nói; Tôi chỉ đang cố gắng để loại bỏ bất kỳ sơ hở có thể có cho *** thông minh.]


Tôi nó, nhưng tôi lo lắng nó sẽ mang lại lợi thế cho những người biết và sử dụng các hương vị không giàu tính năng. Hay những lo lắng của tôi là vô căn cứ?


8
không thể, các dấu ngoặc lồng tùy ý làm cho một biểu thức ngữ pháp không có ngữ cảnh, (thay thế nó bằng một ký hiệu đánh bóng cũng cần một ngăn xếp)
ratchet freak

@ratchet Augh, bạn có thể đúng.
Mateen Ulhaq

1
một số tiện ích mở rộng trên các ngôn ngữ thông thường tồn tại có thể cho phép khớp với dấu ngoặc nhưng tôi không biết cách thực hiện
ratchet freak

8
Điều đó chắc chắn là có thể với các biểu thức Perl.
Peter Taylor

1
@BrianVandenberg các biểu thức chính quy được triển khai trong các ngôn ngữ hiện đại hầu như đều không đều đặn ... ngay khi bạn thêm phản hồi, bạn có thể khớp các ngôn ngữ không thông thường. Hơn nữa, cả Perl / PCRE và .NET đều đủ mạnh để khớp chính xác.
Martin Ender

Câu trả lời:


22

Hồng ngọc

Tôi đã cố gắng khớp với cú pháp thực tế của hương vị regex của Ruby càng nhiều càng tốt, nhưng có một vài điều kỳ quặc: nó chấp nhận một vài cái nhìn thực sự không hợp lệ (như (?<=(?<!))) và nó nhận ra phạm vi ký tự trống như thế nào D-A. Cái sau có thể được sửa cho ASCII, nhưng regex đủ dài.

\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

Phiên bản không thể đọc được:

\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
Cả hai không phải là phiên bản không thể đọc được?
Kibbee

2
@Kibbee Cái đầu tiên có thể đọc được một cách hợp lý nếu bạn biết rõ về regex.
Lowjacker

1
Làm thế nào để đảm bảo rằng không có phản hồi số không hợp lệ?
Martin Ender

1
Tôi đoán nó không. Sau đó, một lần nữa, đó không phải là giới hạn duy nhất mà nó có (xem ở trên). Một số điều có thể được sửa chữa, nhưng regex sẽ trở nên dài một cách lố bịch.
Lowjacker
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.