Несколько дополнительных символов во входной строке приводят к тому, что регулярное выражение не соответствует

У меня есть строка, в которой я запускаю регулярное выражение, но получаю сообщение об ошибке.

PHP:

<?php 
$str = 'modified:   apps/aaaaaa/bbbbbb/cccc
    modified:   apps/ami (new commits)
    modified:   apps/assess (new commits)
    modified:   apps/ees121 (new commits)
    modified:   apps/energy_bourse (new commits)
    modified:   apps/gis (new commits)
    modified:   apps/hse (new commits)
    modified:   apps/aa/aaa/a/bb/b/bb/bc/c22/s/df/s/
    modified:   apps/management (new commits)
    modified:   apps/payesh (new commits)
    modified:   external_apps (modified content)
    modified:   modules/esb_server (new commits)
    modified:   modules/formbuilder (new commits, modified content)
    modified:   modules/reporting (new commits)
    modified:   modules/safir (new commits)
    modified:   modules/workflow (new commits)
    modified:   vendor/raya_framework/client (new commits)
    modified:   vendor/raya_framework/core (new commits)';
preg_match_all("/modified:\s+((\w+\/?)+).*\)/", $str, $matches);
var_dump($matches);

Это нормально работает, но если я добавлю несколько символов в одну из строк, ничего не получится. Например.:

modified:   apps/aaaaaa/bbbbbb/ccccfff

Кажется, это зависит от символов слова, а не от косой черты. Почему некоторые персонажи здесь важны? и что мне делать?

У вас есть несколько злобных квантификаторов, которые заставляют это работать вечно. Это хороший повод для Катастрофический возврат. Вместо этого попробуйте modified:\s+((?>\w++\/?)+)[^\v)]*\).

revo 10.09.2018 08:32

@revo: Если он протестирован, не могли бы вы добавить ответ, чтобы он мог помочь и другим

Bhavin Solanki 10.09.2018 08:34
0
2
106
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Эти дополнительные символы заставляют механизм регулярных выражений достигать предела шагов возврата:

var_dump(preg_last_error() === PREG_BACKTRACK_LIMIT_ERROR); // will return `true`

Ваше регулярное выражение почти короткое и может показаться правильным, но на самом деле оно злоупотребляет квантификаторами и приводит к возникновению Катастрофический возврат при сбоях. Когда ему не удается сопоставить ) в конце последовательности шаблонов \w+/?, он пытается вернуться ко всем предыдущим подвыражениям в надежде найти ). Но этого никогда не происходит, и вложенные количественные группы и токены заставляют этот процесс работать вечно.

Решение перестраивает ваше регулярное выражение, чтобы учесть это:

modified:\s+((?>\w+\/?)+).*\)

Я только что сделал вторую группу захвата атомной группой. Атомные группы - как следует из названия - не допускают возврата в кластер. Поэтому, если ему не удается найти шаблон после сопоставления с \w+\/?, он никогда не возвращается в \w+\/?, и это приводит к преждевременному отказу.

Правильная модификация этого регулярного выражения будет заменять .* чем-то более ограничительным:

modified:\s+((?>\w+\/?)+)[^)\v]*\)

См. живая демонстрация здесь

Код PHP:

preg_match_all('~modified:\s+((?>\w+/?)+)[^)\v]*\)~', $str, $matches);

Спасибо за действительно интересную ссылку о катастрофическом возврате.

Nick 10.09.2018 10:19

Ваше регулярное выражение не захватывает все группы, оно пропускает те, которые следуют за строкой без (new commits) или аналогичной

Nick 10.09.2018 10:33

@Nick Потому что ему нужно найти ) в той же строке. См. Регулярное выражение OP.

revo 10.09.2018 10:35

@Nick Существует также этот ответ, который дает некоторые полезные подсказки при написании регулярного выражения, которое вы, возможно, захотите посмотреть.

revo 10.09.2018 10:35

@Nick Регулярное выражение, которое вы использовали в своей ссылке, не мое. Вы сделали вторую часть необязательной, просто скопируйте / вставьте ее в этом ответе. Но проблема в двойных кавычках. Удалите их и используйте одинарные кавычки. Я тоже отредактирую свой ответ, чтобы отразить это.

revo 10.09.2018 10:54

Ой. это смущает, я играл с твоим и набил. Я удалю этот комментарий ...

Nick 10.09.2018 10:56

Совершенно никаких проблем.

revo 10.09.2018 11:08

Другие вопросы по теме