Там, кажется, какое-то недоразумение об этом
Предположим, что у нас есть строка
my $s = 'xxxxxxxxxx9999</i>)';
затем шаблон совпадающий как этот
$s =~ m<.*?(\d{4})</i>\)>
начнется, если предположить, что .*?
занимает нет символов в начале строки. Затем он проверяет, соответствует ли (\d{4})</i>\)
строке в этой точке
Он не работает, поэтому двигатель регулярного выражения дает один символ x
до .*?
и повторяет попытку. Это также терпит неудачу, поэтому часть строки, потребляемая .*?
, расширена по-символу, пока она не соответствует десяти символам xxxxxxxxxx
.В этот момент остаток шаблона соответствует успешно и тесту регулярного выражения объявляется успехом
Если вместо этого у нас есть, не ленив рисунок на
$s =~ m<.*(\d{4})</i>\)>
Это запустит в предположении, что .*
занимает все строки
Остальная часть рисунка не соответствует в этой точке, поэтому откат начинается за раз, давая .*
все, кроме одного символа строки и повторите попытку
Это повторяется, как и раньше, но сокращение матча характер за символом, пока не будет найдено совпадение, когда он отступал над задними девяти символами строки 9999</i>)
и .*
теперь соответствует xxxxxxxxxx
, как и раньше
Backtracking: Назад к ранее подобранному элементу шаблона, когда совпадение было найдено с ошибкой, изменяя, как этот элемент совпадает и повторяет попытку. Это не будет назад через объект строку ищет что-то
Проблема здесь вызвана .*?
, которая должна учитываться в шаблоне. Если бы у нас было только m<(\d{4})</i>\)>
, тогда вообще никакого возврата нет. Движок регулярных выражений просто ищет \d{4}</i>\)
и либо находит, либо не
Это прекрасно работает до тех пор, как это первого появление узора, который вы хотите. К сожалению, единственный способ найти последнее вхождение подстроки является перед ним .*
, который стартует возвратов и делает процесс обязательно медленнее
выше регулярное выражение медленно, когда я запускаю его через некоторый нормальный размер HTML-страниц?
Несмотря на это, в зависимости от того, какова ваша идея «HTML-страниц нормального размера», я не вижу, чтобы это заняло больше нескольких миллисекунд. Двигатель регулярных выражений закодирован в C и написан очень быстро. Думаю, вы должны запустить таймер, чтобы заметить какую-либо задержку?
Вы считали, что вместо этого используете законный парсер? – hwnd
@hwnd Справедливая точка, но меня действительно интересует, почему такое простое регулярное выражение будет работать так медленно. – CJ7
Все, что вам нужно, это 'm <(\d{4}) \)>'. Это быстрее? Если вы не видите улучшения, то это не регулярное выражение, которое медленное – Borodin