Что означает это регулярное выражение (RegEx) Flag Mean/iD

Я бы хотел использовать это регулярное выражение для проверки IPv6, но я хочу понять все, что он делает qaru.site/info/19824/...

^(?>(?>([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}))$/iD

но я не знаю, что делает этот флаг в конце: /iD. Я знаю, что флаг /i означает игнорировать регистр, но я не могу найти, что D делает где угодно. Этот ответ был одобрен многими, некоторые из них я предполагаю, что он действителен, но в этом сообщении говорится, что флаг D отсутствует: qaru.site/info/20009/...

Я пытаюсь использовать это в PL/SQL, и он не вализует правильную строку правильно:

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}))$/iD') ) then

Ответ 1

Это флаг в стиле PCRE регулярного выражения. См. Примечание на странице руководства PHP.net:

http://php.net/manual/en/reference.pcre.pattern.modifiers.php (в примерах кода)

D (PCRE_DOLLAR_ENDONLY) -     Если этот модификатор установлен, метасимвол доллара в шаблоне совпадает только с     конец строки темы. Без этого модификатора доллар также соответствует     непосредственно перед окончательным символом, если это символ новой строки     (но не раньше других строк новой строки). Этот модификатор игнорируется     если m модификатор установлен. В Perl нет эквивалента этому модификатору.

Ответ 2

D флаг действителен только в PCRE. Ниже приведено документация по PHP:

D (PCRE_DOLLAR_ENDONLY)

Если этот модификатор установлен, метасимвол доллара в шаблоне соответствует только в конце строки темы. Без этого модификатора доллар также соответствует непосредственно перед конечным символом, если он является символом новой строки (но не раньше любых других строк перевода). Этот модификатор игнорируется, если установлен m-модификатор. В Perl нет эквивалента этому модификатору.

Резюме

Это регулярное выражение в цвете PCRE соответствует следующему формату:

  • IPv6: 2001:0db8:85a3:0000:0000:8a2e:0370:7334
  • IPv6 с ведущим 0 пропущен: 2001:db8:85a3:0:0:8a2e:370:7334
  • IPv6 с длинными последовательными группами из 0 (разрыв по левому краю) удален: 2001:db8:85a3::8a2e:370:7334, 2001:db8::1:0:0:1
  • IPv6-пунктирная обозначение: ::ffff:192.0.2.128
  • IPv4: 192.0.2.128

Обратите внимание, что разрешен простой IPv4, возможно, из-за поддержки авторского решения. Это можно легко исключить, удалив ?, где я прокомментировал ниже.

Регулярное выражение соответствует всем действительным IPv6 в соответствии с частью 2.2 RFC 4291. Тем не менее, это не подходит для проверки того, находится ли IPv6 в его канонической форме, как предложено RFC 5952

Обозначение шаблона

Я использую термин hexa-group для ссылки на 16-битную группу в адресе IPv6, который записывается в десятичной форме с десятичной точностью. И deci-group для ссылки на 8-битную группу в адресе IPv4, который написан в десятичной форме с десятичной точностью.

^
(?>
  (?>
                                    # Below matches expanded IPv6
    ([a-f0-9]{1,4})                 # (Hexa-group) One to 4 hexadecimal digits
    (?>:(?1)){7}                    # Match 7 (: hexa-group)

    |                               # OR

                                    # Below matches shorthand notation :: IPv6
    (?!(?:.*[a-f0-9](?>:|$)){8,})   # Can't find 8 or more hexa-groups ahead
    ((?1)(?>:(?1)){0,6})?           # Match 0 to 7 hexa-groups, delimited by :
    ::                              # ::
    (?2)?                           # Match 0 to 7 hexa-groups, delimited by :
  )
  |
                                 # Below match IPv4 or IPv6 dotted-quad notation
  (?>                            
                                 # Below matches first 96-bit of IPv6
    (?>                          
                                 # Below matches expanded notation
      (?1)(?>:(?1)){5}:          # Match one hexa-group then 5 times (: hexa-group)

      |                          # OR

                                 # Below matches shorthand notation
      (?!(?:.*[a-f0-9]:){6,})    # Can't find 6 or more hexa-groups ahead
      (?3)?                      # Match 0 to 7 hexa-groups, delimited by :
      ::                         # ::
      (?>((?1)(?>:(?1)){0,4}):)? # Match 0 to 7 hexa-groups, delimited by :
    )?                           # Optional, so the regex can also match IPv4

                                 # Below matches IPv4 in dotted-decimal notation
    (25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9]) # (Deci-group) One IPv4 deci-group
    (?>\.(?4)){3}                               # Match 3 (. deci-group)
  )
)
$

Вы можете задаться вопросом, почему я написал # Match 0 to 7 hexa-groups, delimited by : для той части, где вы сопоставляете короткую нотацию для нотации IPv6 с точками. Это связано с повторным использованием шаблона с помощью вызова подпрограммы (?3). Однако регулярное выражение не является ошибочным: из-за более раннего поиска (?!(?:.*[a-f0-9]:){6,}) невозможно найти более 5 гекса-групп, если вы соответствуете короткой нотации для нотации IPv6 с точками.

Ошибка

Кстати, в исходном регулярном выражении есть ошибка. Он не соответствует ::129.144.52.38 из-за первой группы без обратной отслеживания (?>pattern), запрещающей обратное отслеживание, тогда как часть шаблона, соответствующая сокращению IPv6, не имеет достаточной проверки, чтобы убедиться, что впереди нет нотации IPv6 с точками. Проще говоря: :: может быть короткозахватным IPv6 и также может быть префиксом для нотации с обозначением IPv6 с точками и без возврата двигателя не соответствует ::129.144.52.38.

DEMO (Примечание: флаги g и m предназначены для тестирования)

Один быстрый способ исправить - изменить первый > на :. Все IPv6 должны быть согласованы правильно, как предполагалось.

DEMO (Примечание: флаги g и m предназначены для тестирования)