IPv6 Regular Expression (RegEx) Not Working in PL/SQL

拥有回忆 提交于 2019-12-06 05:24:44

Instead of doing everything in a single regex, it is better to break the regex into smaller ones and test them:

if (
    /* IPv6 expanded */
    REGEX_LIKE(v, '\A[a-f0-9]{1,4}(:[a-f0-9]{1,4}){7}\z', 'i')
    /* IPv6 shorthand */
    OR (NOT REGEX_LIKE(v, '\A(.*?[a-f0-9](:|\z)){8}', 'i')
        AND REGEX_LIKE(v, '\A([a-f0-9]{1,4}(:[a-f0-9]{1,4}){0,6})?::([a-f0-9]{1,4}(:[a-f0-9]{1,4}){0,6})?\z', 'i'))
    /* IPv6 dotted-quad notation, expanded */
    OR REGEX_LIKE(v, '\A[a-f0-9]{1,4}(:[a-f0-9]{1,4}){5}:(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}\z', 'i')
    /* IPv6 dotted-quad notation, shorthand */
    OR (NOT REGEX_LIKE(v, '\A(.*?[a-f0-9]:){6}', 'i')
        AND REGEX_LIKE(v, '\A([a-f0-9]{1,4}(:[a-f0-9]{1,4}){0,4})?::([a-f0-9]{1,4}:){0,5}(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}\z', 'i'))
   ) then

This only tests for IPv6. IPv4 is not allowed.

Since PL/SQL flavor doesn't have subroutine calls (?n), there is no choice but to expand everything out. And the lack of negative look-ahead (?!pattern) forces us to simulate it with 2 regex testing operations.

\A and \z are used for matching beginning and the end of the string, since both of them are not affected by flags, and \z behavior is the same as $ under D mode in PCRE.

You have to get rid of the / at the start and the /iD from the end this is part of the perl syntax indicating it is a regex.

the i switch at the end means ignore case and can be given as an extra argument of your regexp_like, so:

if ( REGEXP_LIKE(v,'^(?>(?>([a-f0-9]{1,4})(?>:(?1)){7}|(?!(?:.*[a-f0-9](?>:|$)){8,})((?1)(?>:(?1)){0,6})?::(?2)?)|(?>(?>(?1)(?>:(?1)){5}:|(?!(?:.*[a-f0-9]:){6,})(?3)?::(?>((?1)(?>:(?1)){0,4}):)?)?(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(?>\.(?4)){3}))$','i') ) the

There are more issues, as perl regular expressions are not 100% equivalent to oracle regular expressions, and I see patter used here that are not available like ?> Maybe you can split up the regexp between ipv4 and ipv6 to avoid hitting the limit in oracle. And just do REGEXP_LIKE(ip,'ipv4pattern') or REGEXP_LIKE(ip,'ipv6pattern')

Adjusting the ipv4 part of the above regex to something that works in oracle gives me:

REGEXP_LIKE(ip,'^((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])$','i')
Aeron
REGEXP_LIKE(ip,'^(([\dA-F]{1,4}:([\dA-F]{1,4}:([\dA-F]{1,4}:([\dA-F]{1,4}:([\dA-F]{1,4}:[\dA-F]{0,4}|:[\dA-F]{1,4})?|(:[\dA-F]{1,4}){0,2})|(:[\dA-F]{1,4}){0,3})|(:[\dA-F]{1,4}){0,4})|:(:[\dA-F]{1,4}){0,5})((:[\dA-F]{1,4}){2}|:(25[0-5]|(2[0-4]|1\d|[1-9])?\d)(\.(25[0-5]|(2[0-4]|1\d|[1-9])?\d)){3})|(([\dA-F]{1,4}:){1,6}|:):[\dA-F]{0,4}|([\dA-F]{1,4}:){7}:)\z', 'i')

Modified from the XML regex at http://home.deds.nl/~aeron/regex/

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!