我试图编写一个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>
我无法找到解决方法 - 因为我对正则表达式非常不熟悉,并且不知道这个问题的正确措辞。这个问题有一个简单而有效的解决方案吗?
答案 0 :(得分:3)
不幸的是,实际上并没有那么繁琐的方法。
关于您的模式:请注意,GtkSourceView
使用的是PCRE正则表达式引擎,它是NFA正则表达式引擎。因此,当您编写一个替换时,匹配的第一个替代(从左到右)将成功,并且正则表达式引擎将不会在右侧更远的地方测试其他替代,例如字符串{{1}模式abcdef
将返回(a|ab|abc|abcde|abcdef)
(当DFA返回匹配的最长选项时,a
)
这意味着你的模式只是因为末尾有一个词边界(对于整个词abcdef
,每个备选都成功,但是一旦达到词边界,正则表达式引擎必须回溯并测试下一个替代方案,直到最后一个。)
结论,最好将最长的替代品写成最短的替代品,以避免对引擎进行不必要的工作,所以:
variable
另一种可能性就是设计你的模式:
\bvari(able|abl|ab|a)?\b
在这种情况下,正则表达式引擎直接进入模式的末尾,而不必找到良好的交替。但请注意,写入并不是更简单,但由于您不必多次写信,所以写得更短一些!