2

我正在尝试编写一个 GtkSourceView 语言文件来突出显示我在 gedit 中的一些文件。我遇到的问题是我想突出显示至少包含前四个字符并且拼写正确的单词。为了说明,假设我有四种模式:

variable
vari
variab
variabel

我想识别前三个,但不是第四个,因为前三个都是目标“变量”的正确拼写的子字符串。完成工作的是使用

\bvari(a|ab|abl|able)?\b

但这可能会因较长的单词而变得非常乏味。所以在一个完整的语言文件中,它看起来像这样:

<?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>

我无法找到解决方案 - 因为我对正则表达式非常不熟悉,也不知道这个问题的正确措辞。这个问题有简单有效的解决方案吗?

4

1 回答 1

3

不幸的是,没有真正不那么乏味的方法来做到这一点。

关于您的模式:请注意,它GtkSourceView使用的是 NFA 正则表达式引擎的 PCRE 正则表达式引擎。因此,当您编写替代方案时,匹配的第一个替代方案(从左到右)将成功,并且正则表达式引擎不会在更远的右侧测试其他替代方案,例如abcdef模式(a|ab|abc|abcde|abcdef)将返回的字符串a (当 DFA 将返回最长的匹配项,所以abcdef)

这意味着您的模式之所以有效,只是因为末尾有一个单词边界(对于整个 word variable,每个备选方案都会成功,但是一旦达到单词边界,正则表达式引擎必须回溯并测试下一个备选方案,依此类推,直到最后一个.)

结论,最好从最长的替代方案到最​​短的替代方案编写您的替代方案,以避免对引擎进行不必要的工作,因此:

\bvari(able|abl|ab|a)?\b

另一种可能性是像这样设计您的模式:

\bvari(a(b(le?)?)?)?\b

在这种情况下,正则表达式引擎直接进入模式的末尾,而不必找到好的交替。但请注意,它不是更简单,而是更短一些,因为您不必多次写信!

于 2015-01-28T16:24:56.537 回答