У меня есть регулярное выражение, которое будет использоваться для соответствия тегам @users.
Я использую утверждения lokarround, позволяя пунктуации и пробелам окружать теги.
Есть дополнительное осложнение, есть тип bbcodes, которые представляют html.
У меня есть два типа BB-коды, встроенные (^B
смелый ^b
) и блоки (^C
центр ^c
).
Встроенные должны быть переданы через, чтобы добраться до предыдущего или следующего символа.
И блоки могут окружать тег, как пунктуация.
Я сделал регулярное выражение, которое работает. То, что я хочу сделать сейчас, это уменьшить количество шагов, которые он делает для каждого персонажа, который не будет совпадать.
Сначала я думал, что мог бы сделать регулярное выражение, которое будет просто искать @
и когда он будет найден, он начнет смотреть на обходные пути, которые работают без встроенных bb-кодов, но поскольку просмотр за пределами не может быть количественно измерим, это сложнее, так как я не могу добавить ((\^[BIUbiu])++)*
внутри, производя гораздо больше шагов.
Как я могу сделать свое регулярное выражение более эффективным с меньшим количеством шагов?
Вот его упрощенная версия, в ссылке Regex101 есть полное регулярное выражение.
(?<=[,\.:=\^ ]|\^[CJLcjl])((\^[BIUbiu])++)*@([A-Za-z0-9\-_]{2,25})((\^[BIUbiu])++)*(?=[,\.:=\^ ]|\^[CJLcjl])
Правило большого пальца:
Не позволяйте движку пытаться сопоставить каждый отдельный символ, если
Есть некоторые границы.
Цитата изначально исходит из этого ответа. Следующее регулярное выражение значительно уменьшает шаги из-за левой стороны самого внешнего чередования, от ~ 20000 до ~ 900:
(?:[^@^]++|[@^]{2,}+)(*SKIP)(*F)
|
(?<=([HUGE-CHARACTER-CLASS])|\^[cjleqrd])
(\^[34biu78])*+@([a-z\d][\w-.]{0,25}[a-z\d])(\^[34biu78])*+(?=(?1))
На самом деле меня не волнует количество шагов, о которых сообщает regex101, потому что это не может быть правдой в вашей среде, и неясно, являются ли некоторые шаги реальными или нет, или какие шаги пропущены. Но в этом случае, поскольку логика регулярных выражений ясна, а разница велика, это имеет смысл.
В чем логика?
Сначала мы пытаемся сопоставить то, что, вероятно, вообще нежелательно, выбрасываем это и ищем части, которые могут соответствовать нашему шаблону. [^@^]++
соответствует до @
или же ^
символы (нужные символы) и [@^]{2,}+
препятствует тому, чтобы двигатель предпринял дополнительные шаги прежде, чем обнаружить, что это никуда не идет. Таким образом, мы делаем это, чтобы потерпеть неудачу как можно скорее.
Ты можешь использовать i
флаг вместо определения прописных букв (это может оказать небольшое влияние).
Увидеть живое демо здесь
Других решений пока нет …