使用正则表达式有效匹配参数的正确拼写部分
Efficiently matching correctly spelled parts of arguments with regex
我正在尝试编写一个 GtkSourceView 语言文件来突出显示我在 gedit 中的一些文件。我遇到的问题是我想突出显示至少包含前四个字符且拼写正确的单词。为了说明,假设我有四种模式:
variable
vari
variab
variabel
我想识别前三个,而不是第四个,因为前三个都是目标 "variable" 的正确拼写子字符串。完成工作的方法是使用
\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>
我找不到这个问题的解决方案 - 因为我对正则表达式非常不熟悉,也不知道这个问题的正确措辞。这个问题有没有简单高效的解决方案?
不幸的是,没有比这更简单的方法了。
关于您的模式:请注意,GtkSourceView
使用 PCRE 正则表达式引擎,它是一个 NFA 正则表达式引擎。因此,当您编写替代方案时,匹配的第一个替代方案 (从左到右) 将成功,并且正则表达式引擎将不会测试右侧更远的其他替代方案,例如字符串 abcdef
模式 (a|ab|abc|abcde|abcdef)
将 return a
(当 DFA 将 return 匹配的最长备选方案时,因此 abcdef
)
这意味着您的模式之所以有效,只是因为末尾有一个词边界 (对于整个词 variable
,每个替代方案都会成功,但是一旦达到词边界,正则表达式引擎必须回溯并测试下一个替代方案,依此类推直到最后一个。)
结论,最好从最长的备选方案到最短的备选方案来编写您的备选方案,以避免对引擎造成不必要的工作,因此:
\bvari(able|abl|ab|a)?\b
另一种可能性是像这样设计你的模式:
\bvari(a(b(le?)?)?)?\b
在这种情况下,正则表达式引擎直接进入模式的末尾,而不必找到好的交替。但是请注意,它不是更简单,而是更短一些,因为您不必多次写字母!
我正在尝试编写一个 GtkSourceView 语言文件来突出显示我在 gedit 中的一些文件。我遇到的问题是我想突出显示至少包含前四个字符且拼写正确的单词。为了说明,假设我有四种模式:
variable
vari
variab
variabel
我想识别前三个,而不是第四个,因为前三个都是目标 "variable" 的正确拼写子字符串。完成工作的方法是使用
\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>
我找不到这个问题的解决方案 - 因为我对正则表达式非常不熟悉,也不知道这个问题的正确措辞。这个问题有没有简单高效的解决方案?
不幸的是,没有比这更简单的方法了。
关于您的模式:请注意,GtkSourceView
使用 PCRE 正则表达式引擎,它是一个 NFA 正则表达式引擎。因此,当您编写替代方案时,匹配的第一个替代方案 (从左到右) 将成功,并且正则表达式引擎将不会测试右侧更远的其他替代方案,例如字符串 abcdef
模式 (a|ab|abc|abcde|abcdef)
将 return a
(当 DFA 将 return 匹配的最长备选方案时,因此 abcdef
)
这意味着您的模式之所以有效,只是因为末尾有一个词边界 (对于整个词 variable
,每个替代方案都会成功,但是一旦达到词边界,正则表达式引擎必须回溯并测试下一个替代方案,依此类推直到最后一个。)
结论,最好从最长的备选方案到最短的备选方案来编写您的备选方案,以避免对引擎造成不必要的工作,因此:
\bvari(able|abl|ab|a)?\b
另一种可能性是像这样设计你的模式:
\bvari(a(b(le?)?)?)?\b
在这种情况下,正则表达式引擎直接进入模式的末尾,而不必找到好的交替。但是请注意,它不是更简单,而是更短一些,因为您不必多次写字母!