许多Unix工具的正则表达式语法通常是POSIX编码的基本正则表达式和扩展正则表达式(分别是BRE和ERE),在某些现代实现中,是Perl样式(PCRE是这种实现)。
Vim的魔术等级与此类外部定义但众所周知的类之间是否存在一对一的对应关系?看起来\m
是BRE,\v
是ERE,但POSIX不包含环视。
如果存在这种对应关系,是否在某处定义?pattern.txt
只提了一则POSIX
。
还是我们必须坚持用“魔术”来描述Vim正则表达式?
许多Unix工具的正则表达式语法通常是POSIX编码的基本正则表达式和扩展正则表达式(分别是BRE和ERE),在某些现代实现中,是Perl样式(PCRE是这种实现)。
Vim的魔术等级与此类外部定义但众所周知的类之间是否存在一对一的对应关系?看起来\m
是BRE,\v
是ERE,但POSIX不包含环视。
如果存在这种对应关系,是否在某处定义?pattern.txt
只提了一则POSIX
。
还是我们必须坚持用“魔术”来描述Vim正则表达式?
Answers:
总之,没有。Vim的正则表达式是一种独特的风味,没有选择使其表现得更像另一种风味。
我认为这是一件好事。
该'magic'
选项不会改变Vim使用的正则表达式的风格。它只是简单地反转了许多\
转义原子的行为。
例如,默认情况下+
是文字+
字符,其中\+
表示“一个或多个前面的原子”。相反,*
表示“零个或多个在前原子”,而\*
则是一个文字*
。许多人觉得这很混乱。\v
在您的模式中使用会使它更加一致。:help 'magic'
给出了一个很好的总结:
after: \v \m \M \V matches ~ 'magic' 'nomagic' $ $ $ \$ matches end-of-line . . \. \. matches any character * * \* \* any number of the previous atom () \(\) \(\) \(\) grouping into an atom | \| \| \| separating alternatives \a \a \a \a alphabetic character \\ \\ \\ \\ literal backslash \. \. . . literal dot \{ { { { literal '{' a a a a literal 'a'
就个人而言,我认为默认行为对于代码文件而言是不错的选择,在这种情况下foo(
,使用literal 搜索诸如之类的事情并不罕见(
。
我见过很多人希望Vim支持PCRE。我个人希望其他工具支持Vim的正则表达式。它具有某些在PCRE中无法实现或过于繁琐的功能。
环视是一项常见功能,您可以断言某个模式在尝试匹配的模式之前或之后是否匹配。例如,PCRE模式q(?!u)
(或Vim regex模式qu\@!
)匹配一个q
后跟一个的u
。(这比正确q[^u]
,因为它要求在。之后有一些字符q
。)
PCRE和许多其他口味都有一个局限性,即负向后看图案必须具有固定的长度。这就意味着,类似这样的模式是好的,但它的(?<![a-z]{3})foo
含义是“该字符串foo
不以 3个小写字母开头”,但(?<![a-z]+)foo
“以字符串foo
不以任何数量的小写字母开头”则不是。
这个限制在Vim中不存在。在Vim中,类似的模式\([a-z]\+\)\@<!foo
虽然看起来有些丑陋,但却是完全有效的。
Vim的正则表达式风格有些东西要好得多。
我认为,最值得注意的是\zs
和\ze
锚。这些允许您指定比赛的开始和结束。例如,foo(\zs.*\ze)
仅匹配(
和之类)
的函数调用之间的foo(...)
。这可以在PCRE中完成,但是需要使用环视功能,这有点乏味:(?<=foo\().*(?=\))
Vim可以做的另一件很酷的事情是匹配特定字符序列的任何前缀(包括空前缀)。例如,为了匹配f
,fo
,foo
,或food
,该图案f\%[ood]
可以被使用。在PCRE中,这种模式看起来像f(o(od?)?)?
。(想象一下,更长的字符串!)
Vim的正则表达式具有一些锚点,用于匹配缓冲区中的位置。
\%23c
匹配第23列\%<23c
第23栏之前的比赛\%>23c
在第 23列之后进行匹配\%16l
符合第16行
\%#
匹配光标位置
我认为值得Vim接受正则表达式。它非常适合在主要用于编程的文本编辑器中使用,并且功能非常强大。
\v
包括<>
字边界,这AFAIK是Vim独有的。因此,不,只需将它们描述为“ Vim regex”即可。(因为我不积极,所以不发布答案)