Эффективное сопоставление правильно записанных частей аргументов с регулярным выражением

Я пытаюсь написать языковой файл 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

В этом случае движок регулярных выражений идет прямо к концу шаблона без необходимости искать хорошее чередование. Но обратите внимание, что это не так просто написать, но немного короче, так как вам не нужно писать письма несколько раз!

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