powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / PHP, Perl, Python [игнор отключен] [закрыт для гостей] / (php) Сферический конь в вакууме на регулярках (preg_match_all)
7 сообщений из 7, страница 1 из 1
(php) Сферический конь в вакууме на регулярках (preg_match_all)
    #39946252
Cyrax_02
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Пример 1 (результат корректный, ожидаемый):
Код: php
1.
2.
3.
$str = "1 <01> 2 <PP> 3";
$regexpr = '/<(?<DIGIT>\d+)>|<(?<LETTER>\w+)>/u';
preg_match_all($regexpr, $str, $matches, PREG_PATTERN_ORDER);

Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
Array
(
    [0] => Array
(
	[0] => "<01>"
	[1] => "<PP>"
        )
    [DIGIT] => Array
(
	[0] => "01"
	[1] => ""
        )
    [1] => Array
(
	[0] => "01"
	[1] => ""
        )
    [LETTER] => Array
(
	[0] => ""
	[1] => "PP"
        )
    [2] => Array
(
	[0] => ""
	[1] => "PP"
        )
)


Пример 2 (результат корректный, ожидаемый):
Код: php
1.
2.
3.
$str = "1 <01> 2 <PP> 3";
$regexpr = '/<(?<DIGIT>\d+)>|<(?<LETTER>\w+)>/u';
preg_match_all($regexpr, $str, $matches, PREG_SET_ORDER);

Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
Array
(
    [0] => Array
(
	[0] => "<01>"
	[DIGIT] => "01"
        [1] => "01"
        )
    [1] => Array
(
	[0] => "<PP>"
	[DIGIT] => ""
        [1] => ""
        [LETTER] => "PP"
        [2] => "PP"
        )
)


Пример 3 . Объединим именные карманы DIGIT и LETTER в один общий карман CHAR с помощью опции (?J)
Код: php
1.
2.
3.
$str = "1 <01> 2 <PP> 3";
$regexpr = '/(?J)<(?<CHAR>\d+)>|<(?<CHAR>\w+)>/u';
preg_match_all($regexpr, $str, $matches, PREG_SET_ORDER);

Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
Array
(
    [0] => Array
(
        [0] => "<01>"
	[CHAR] => "01"    // объединённый карман
        [1] => "01"
        )
    [1] => Array
(
	[0] => "<PP>"
	[CHAR] => "PP"    // объединённый карман
        [1] => ""         // индексные карманы НЕ объединяет, ну да и ладно (главное, объединил именные карманы)
        [2] => "PP"
        )
)


Пример 4 . Объединённый карман + PREG_PATTERN_ORDER
Код: php
1.
2.
3.
$str = "1 <01> 2 <PP> 3";
$regexpr = '/(?J)<(?<CHAR>\d+)>|<(?<CHAR>\w+)>/u';
preg_match_all($regexpr, $str, $matches, PREG_PATTERN_ORDER);

Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
Array
(
    [0] => Array
        (
            [0] => "<01>"
            [1] => "<PP>"
        )
    [CHAR] => Array
        (
            [0] => ""    // где "01" ???
            [1] => "PP"
        )
    [1] => Array
        (
            [0] => "01"
            [1] => ""
        )
    [2] => Array
        (
            [0] => ""
            [1] => "PP"
        )
)


Вот здесь мы получили сферического коня в вакууме. Исходя из логики опции (?J) , карман с ключом "CHAR" должен иметь вид ["01", "pp"], а не ["", "pp"]. Т.е. объединения именных карманов не произошло и второй карман с именем "CHAR" перезаписал первый карман с именем "CHAR".

Возможны 3 варианта :
1) Особенность "объединения" одноимённых карманов в режиме PREG_PATTERN_ORDER, которую я понять не могу
2) Bug версии php 5.6, исправленный в версии 7.x
3) Bug версии php 7.x тоже, до сих пор не исправленный

Для справки :
авторIf you are using named patterns you can now have the same name multiple times, provided you put the " (?J) " option in your pattern. For example: Match: (?J)(?P<name>Ni.+)|(?P<name>Fr.+)
This would match "Nick" or "Fred", and whichever one matched, the named pattern "name" would be set to it.
The (?J) internal option setting changes the local PCRE_DUPNAMES option. Allow duplicate names for subpatterns. As of PHP 7.2.0 J is supported as modifier as well.
...
Рейтинг: 0 / 0
(php) Сферический конь в вакууме на регулярках (preg_match_all)
    #39947018
Cyrax_02
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Может, кто проверит в php 7.2+ регулярное выражение из примера 4 в режиме PREG_PATTERN_ORDER :
'/(?J)<(?<CHAR>\d+)>|<(?<CHAR>\w+)>/u'
...
Рейтинг: 0 / 0
(php) Сферический конь в вакууме на регулярках (preg_match_all)
    #39947057
vkle
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Cyrax_02
Может, кто проверит в php 7.2+ регулярное выражение из примера 4 в режиме PREG_PATTERN_ORDER :
'/(?J)<(?<CHAR>\d+)>|<(?<CHAR>\w+)>/u'


PHP 7.3.16 (cli) и PHP 7.2.29 (cli) одинаково
Код: php
1.
2.
3.
4.
<?php
$str = "1 <01> 2 <PP> 3";
$regexpr = '/(?J)<(?<CHAR>\d+)>|<(?<CHAR>\w+)>/u';
preg_match_all($regexpr, $str, $matches, PREG_PATTERN_ORDER);


Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
array(4) {
  [0] =>
  array(2) {
    [0] =>
    string(4) "<01>"
    [1] =>
    string(4) "<PP>"
  }
  'CHAR' =>
  array(2) {
    [0] =>
    string(0) ""
    [1] =>
    string(2) "PP"
  }
  [1] =>
  array(2) {
    [0] =>
    string(2) "01"
    [1] =>
    string(0) ""
  }
  [2] =>
  array(2) {
    [0] =>
    string(0) ""
    [1] =>
    string(2) "PP"
  }
}
...
Рейтинг: 0 / 0
(php) Сферический конь в вакууме на регулярках (preg_match_all)
    #39947087
Cyrax_02
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Плохи дела... Не исправили в 7.x .
vkle , если не сложно, ещё одно регулярное выражение (здесь второй "CHAR" всегда пуст => перезаписывает/очищает объединённый "CHAR"):
Код: php
1.
2.
3.
$str = "1 <01>2 <PP>3";  // здесь проблема наблюдается в обоих режимах
$re = '/(?J)(?:<(?<CHAR>\d+)>|@(?<CHAR>0+)@)(?P<END>\d+)/u';
preg_match_all($re, $str, $matches, PREG_SET_ORDER);  // PREG_PATTERN_ORDER

Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
Array
(
    [0] => Array
        (
            [0] => "<01>2"
            [CHAR] => ""
            [1] => "01"
            [2] => ""
            [END] => "2"
            [3] => "2"
        )
)


P.S. А что, если поставить опцию (?J) в конец регулярного выражения в качестве модификатора: .../u J
Не поможет?
...
Рейтинг: 0 / 0
(php) Сферический конь в вакууме на регулярках (preg_match_all)
    #39947191
vkle
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Cyrax_02
Не исправили в 7.x .
А есть открытый багрипорт? Там, где проблема обозначена. Которую исправить надобно.

Cyrax_02
ещё одно регулярное выражение
Так именно и выводит.

Cyrax_02
Не поможет?
Без изменений
...
Рейтинг: 0 / 0
(php) Сферический конь в вакууме на регулярках (preg_match_all)
    #39947232
Cyrax_02
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
авторА есть открытый багрипорт? Там, где проблема обозначена. Которую исправить надобно.Думал, иногда исправляют без багрепортов.
На bugs.php.net таких багрепортов нет. И нафиг нужно. Работать нужно сейчас, а не через 10 лет.

Регулярные выражения с одноимёнными подмасками переписал на условные подмаски с относительными ссылками. Короче получились и, скорее всего, работать станут быстрее, т.к. не содержат полных альтернатив (только частичные).

P.S . Пример 3 на самом деле тоже глючный. Просто там пустой индексный карман оказался в самом конце, а последние пустые карманы, как известно, удаляются. Если бы там ещё карманы были, то он бы не был удалён и перезаписал (очистил) бы объединённый карман "CHAR"
...
Рейтинг: 0 / 0
(php) Сферический конь в вакууме на регулярках (preg_match_all)
    #39950503
Cyrax_02
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Как оказалось, сабжевый багрепорт был (от 11 ферваля 2020 г.)
Встроенный поиск на bugs.php.net и поиск Яндекса с задачей не справились.

В php 7.4 проблема устранена: пустые вхождения больше не будут записываться в объединённый именной карман
http://bugs.php.net/79257 Bug #79257: Duplicate named groups (?J) prefer last alternative even if not matched
In 7.4 named capture group always returns the content captured in last alternative , no matter which of the alternatives matched.

Looks like the actual problem existed in 7.3 and earlier , but it required slight modification to be reproduced. I'll try to update the bug report to take it into account.

I've fixed this in PHP-7.4 . I don't want to fix this on 7.3. It's a long standing issue, and changes to PCRE matches output are risky.
...
Рейтинг: 0 / 0
7 сообщений из 7, страница 1 из 1
Форумы / PHP, Perl, Python [игнор отключен] [закрыт для гостей] / (php) Сферический конь в вакууме на регулярках (preg_match_all)
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]