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

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

Мне не удалось найти решение для этого, потому что я крайне не знаком с регулярными выражениями и не знаю правильной формулировки для этого вопроса. Есть ли простое и эффективное решение этой проблемы?


person Martin S.    schedule 28.01.2015    source источник


Ответы (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

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

person Casimir et Hippolyte    schedule 28.01.2015