Одноразові підмаски

Як для мінімальної, так і максимальної кількості повторень, якщо наступна частина шаблону зазнає невдачі при співставленні, відбувається повторний аналіз виразу, що повторюється, на предмет того, чи можливе успішне зіставлення всього шаблону при іншій кількості повторень. Трапляються випадки, коли потрібно змінити описану логіку роботи для реалізації специфічного зіставлення або оптимізації шаблону (якщо автор впевнений, що інших варіантів відповідності немає).

В качестве Приклада, рассмотрим шаблон\d+foo у застосуванні до рядка 123456bar

Після того як \d+ буде зіставлений з першими шістьма цифрами, зіставлення "foo" зазнає невдачі. Після цього, у відповідність \d+, буде зіставлено 5 цифр, після чергової невдачі буде зіставлено 4 цифри і таке інше. Зрештою весь шаблон зазнає невдачі. Одноразові підмаски вказують, що й одна частина шаблону було зіставлено, її варто аналізувати повторно. Стосовно наведеного вище прикладу весь шаблон зазнав би невдачі після першого невдалого зіставлення з «foo». Записуються одноразові шаблони за допомогою круглих дужок таким чином: (?>. Наприклад: (?>\d+)bar

Цей вид підмаски запобігає повторному її аналізу Якщо зіставлення наступних елементів зазнають невдачі. Однак це не заважає повторно аналізувати будь-які інші елементи, у тому числі попередні одноразової підмаски.

Іншими словами, підмаски такого типу відповідають тій частині підрядка, якій відповідала б одиночна ізольована маска, заякорена на поточній позиції тексту, що обробляється.

Одноразові підмаски є незахоплюючими. Прості приклади, подібні до наведеного вище, можна охарактеризувати як безумовне захоплення максимальної кількості повторень. В той час як \d+ и\d+? коригуються так, щоб інші частини шаблону так само збіглися (?>\d+) відповідає виключно максимальній довжині послідовності цифр, навіть якщо це призводить до невдачі при зіставленні інших частин шаблону.

Одноразові підмаски можуть включати складніші конструкції, а також можуть бути вкладеними.

Одноразові підмаски можуть використовуватися разом із твердженнями щодо попереднього тексту для опису ефективних зіставлень наприкінці оброблюваного тексту. Розглянемо простий шаблон abcd$ у застосуванні до довгого тексту, який відповідає зазначеній масці. Оскільки пошук відбувається зліва направо, спочатку PCRE шукатиме літеру «a», і лише потім аналізуватиме наступні записи в шаблоні. Якщо шаблон вказано у вигляді ^.*abcd$. У цій ситуації спочатку.* зіставляється з усім рядком, після чого зіставлення зазнає невдачі (оскільки немає наступного символу «a»). Після чого .* зіставляється з усім рядком, крім останнього символу, потім крім двох останніх символів, і таке інше. Зрештою, пошук символу «a» відбувається по всьому рядку. Однак, якщо шаблон записати у вигляді: ^(?>.*)(?<=abcd) повторний аналіз для .* не виконується, і, як наслідок, може відповідати лише всьому рядку цілком. Після цього твердження перевіряє останні чотири символи на збіг з «abcd», і у разі невдачі все зіставлення зазнає невдачі. Для великих обсягів тексту, що обробляється, цей підхід має значний виграш у часі виконання.

Якщо шаблон містить необмежену повторення всередині підмаски, яка також може повторюватися необмежену кількість разів, використання одноразових підмасок дозволяє уникати багаторазових невдалих зіставлень, які тривають досить тривалий час. Шаблон (\D+|<\d+>)*[!?] відповідає необмежену кількість підрядків, які складаються не з цифр, або з цифр ув'язнених у <>, за якими слідує ? або!. Якщо в тексті, що обробляється, містяться відповідності, час роботи регулярного виразу буде невеликий. Але якщо його застосувати до рядка aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa це займе тривалий час. Це пов'язано з тим, що рядок може бути розділений між двома частинами шаблону багатьма способами і всі вони будуть випробувані (у прикладі ми використовували [?!], оскільки у разі одиночного символу в кінці шаблону і PCRE та Perl виконують оптимізацію. Вони запам'ятовують останній одиночний символ і у разі відсутності видають невдачу). Якщо змінити шаблон на ((?>\D+)|<\d+>)*[!?], Чи не цифрові послідовності не можуть бути розірвані, і неможливість зіставлення виявляється набагато швидше.