我正在尝试匹配在使用动作时由vim找到的特定(和匹配之间的内容.)%
更具体地说,我正在寻找一个看起来像这个假设的正则表达式/someKeyword (\{pair}\(.*\))\{pair}/,如果有这样的修饰符\{pair},当应用于正则表达式中的两个正好两个字符时,使得第二个仅匹配,如果它是与第一个匹配的括号(%-明智的).
我正在寻找的模式应该匹配第一个括号的内部内容someKeyword(nb应该处理的代码总是正确括号),如下例所示:
对于子someKeyword ("aaa")匹配将匹配"aaa".同样someKeyword ("aaa)")会匹配"aaa)"并someKeyword(("double-nested stuff"))匹配("double-nested stuff")
但在以下情况下:
(
someKeyword("xyz"))
Run Code Online (Sandbox Code Playgroud)
它应该匹配的地方"xyz".
有没有办法在正则表达式中使用vim的匹配括号功能?如果没有,还有什么其他解决方案可以实现这一目标?
编辑1:匹配的内容可能跨越几行.
这对于vim正则表达式是不可能的(因为允许这种嵌套结构的语言不是常规的),但是可以使用perl提供的"常规"表达式(以及我不太了解的其他语言)和perl可以从vim内部使用.我不喜欢vim-perl绑定(因为它非常有限),但如果你知道所有应该工作的情况,那么你可以使用perl正则表达式的递归功能(需要更新的perl,我有5.12*):
perl VIM::Msg($+{"outer"}) if $curbuf->Get(3) =~ /someKeyword\((?'outer'(?'inner'"(?:\\.|[^"])*"|'(?:[^']|'')*'|[^()]*|\((?P>inner)*\))*)\)/
Run Code Online (Sandbox Code Playgroud)
注意,如果可以避免这样的正则表达式,你应该这样做(因为你依赖于重编译器太多),所以我建议直接使用vim运动:
let s:reply=""
function! SetReplyToKeywordArgs(...)
let [sline, scol]=getpos("'[")[1:2]
let [eline, ecol]=getpos("']")[1:2]
let lchar=len(matchstr(getline(eline), '\%'.ecol.'c.'))
if lchar>1
let ecol+=lchar-1
endif
let text=[]
let ellcol=col([eline, '$'])
let slinestr=getline(sline)
if sline==eline
if ecol>=ellcol
call extend(text, [slinestr[(scol-1):], ""])
else
call add(text, slinestr[(scol-1):(ecol-1)])
endif
else
call add(text, slinestr[(scol-1):])
let elinestr=getline(eline)
if (eline-sline)>1
call extend(text, getline(sline+1, eline-1))
endif
if ecol<ellcol
call add(text, elinestr[:(ecol-1)])
else
call extend(text, [elinestr, ""])
endif
endif
let s:reply=join(text, "\n")
endfunction
function! GetKeywordArgs()
let winview=winsaveview()
keepjumps call search('someKeyword', 'e')
setlocal operatorfunc=SetReplyToKeywordArgs
keepjumps normal! f(g@i(
call winrestview(winview)
return s:reply
endfunction
Run Code Online (Sandbox Code Playgroud)
你可以使用类似的东西
let savedureg=@"
let saved0reg=@0
keepjumps normal! f(yi(
let s:reply=@"
let @"=savedureg
let @0=saved0reg
Run Code Online (Sandbox Code Playgroud)
而不是operatorfunc来保存和恢复寄存器,但上面的代码保持所有寄存器和标记不变,我不能保证保存*的东西.这也保证了,如果你删除join()身边text,你会节省约NULL值的位置信息(如果你关心,当然他们,).寄存器变体是不可能的.