Эффективное сопоставление правильно записанных частей аргументов с регулярным выражением
Я пытаюсь написать языковой файл GtkSourceView, чтобы выделить некоторые из моих файлов в gedit. Проблема, с которой я сталкиваюсь, заключается в том, что я хочу выделить слова, которые содержат как минимум первые четыре символа и написаны правильно. Для иллюстрации скажем, у меня есть четыре шаблона:
variable
vari
variab
variabel
и я хочу идентифицировать первые три, но не четвертый, потому что первые три - все правильно написанные подстроки целевой "переменной". То, что получает работа, использует
\bvari(a|ab|abl|able)?\b
но это может стать довольно утомительным с более длинными словами. Так что в полном lang-файле это будет выглядеть примерно так:
<?xml version="1.0" encoding="UTF-8"?>
<language id="foo" _name="foo" version="2.0" _section="Other">
<metadata>
<property name="mimetypes">text/x-foo</property>
<property name="globs">*.foo</property>
</metadata>
<styles>
<style id="keyword" _name="Keyword" map-to="def:keyword"/>
</styles>
<default-regex-options case-sensitive="false"/>
<definitions>
<context id="foo">
<include>
<context id="keyword" style-ref="keyword">
<keyword>\bvari(a|ab|abl|able)\b</keyword>
</context>
</include>
</context>
</definitions>
</language>
Я не смог найти решение этой проблемы - потому что я крайне незнаком с регулярным выражением и не знаю правильной формулировки для этого вопроса. Есть ли простое и эффективное решение этой проблемы?
1 ответ
К сожалению, на самом деле нет менее утомительного способа сделать это.
О вашей модели: обратите внимание, что GtkSourceView
использует механизм регулярных выражений PCRE, который является механизмом регулярных выражений NFA. Поэтому, когда вы пишете чередование, первая альтернатива (слева направо), которая будет соответствовать, будет успешной, и механизм регулярных выражений не будет проверять другие альтернативы, находящиеся далеко справа, например, для строки abcdef
шаблон (a|ab|abc|abcde|abcdef)
вернусь a
(когда DFA вернет самую длинную альтернативу, соответствующую abcdef
)
Это означает, что ваш шаблон работает только потому, что в конце есть граница слова (для всего слова variable
каждая альтернатива успешна, но как только достигнута граница слова, механизм регулярных выражений должен вернуться назад и проверить следующую альтернативу и так далее до последней.)
Вывод: лучше написать чередование от самой длинной альтернативы к самой короткой, чтобы избежать ненужной работы с двигателем, поэтому:
\bvari(able|abl|ab|a)?\b
Другая возможность состоит в том, чтобы разработать свой шаблон так:
\bvari(a(b(le?)?)?)?\b
В этом случае движок регулярных выражений идет прямо к концу шаблона без необходимости искать хорошее чередование. Но обратите внимание, что это не так просто написать, но немного короче, так как вам не нужно писать письма несколько раз!