我想替换每次出现的“foo {...}”除了括号内的换行符(可能有空格,其他括号打开和关闭等),后面跟着“bar”。< / p>
例如,“foo {{}},bar”中的“foo {{}}”匹配但不匹配“foo {hello {}} bar”。
我已尝试/foo{.*}\(bar\)\@!
和/foo{.\{-}}\(bar\)\@!
,但第一个匹配“foo {} bar {}”,第二个匹配“foo {{}} bar”(只有“foo” {{}“部分)。
答案 0 :(得分:0)
这个正则表达式:
foo{.*}\([}]*bar\)\@!
匹配:
foo{{ }}
foo{{ }}, bar
但不是:
foo{hello{}}bar
答案 1 :(得分:0)
无法正确匹配任意级别的嵌套 括号使用正则表达式。但是,有可能 构建一个正则表达式来匹配支持有限数量的嵌套(I 认为这个答案没有尝试这样做)。 - 本
这确实......
最多一层内括号:
/foo{[^{}]*\({[^{}]*}[^{}]*\)*}\(bar\)\@!
最多两层内括号:
/foo{[^{}]*\({[^{}]*\({[^{}]*}[^{}]*\)*}[^{}]*\)*}\(bar\)\@!
最多三层内括号:
/foo{[^{}]*\({[^{}]*\({[^{}]*\({[^{}]*}[^{}]*\)*}[^{}]*\)*}[^{}]*\)*}\(bar\)\@!
...
答案 2 :(得分:0)
取决于您想要准确执行的替换,您也许可以使用宏来做到这一点。
例如:给定这段文字
line 1 -- -- -- -- array[a][b[1]]
line 2 -- array[c][d]
line 3 -- -- -- -- -- -- -- array[e[0]][f] + array[g[0]][h[0]]
将 array[A][B]
替换为 get(A, B)
。
这样做:
/array<cr>
qq
开始录制宏%
去匹配括号,使用some register/mark/plugin删除括号周围)。例如 cwget(<esc>ldi[vhpa, <esc>ldi[vhpa)<esc>n
-- 但宏通常是不可读的。n
转到下一场比赛,q
停止录制@q
重复使用(@@
可以从第二次开始使用)这可能不太方便,因为很容易出错(例如按I
、<home>
、A
)并且您必须从头开始重做宏,但是它有效。
或者,您可以执行类似于 eregex.vim
插件的一些操作来扩展 vim 的正则表达式格式以支持这一点(因此您不必每次都重新键入庞大的正则表达式)。
概念证明:
"does not handle different magic levels
"does not handle '\/' or different characters for substitution ('s#a#b#')
"does not handle brackets inside strings
" usage: `:M/pattern, use \zm for matching block/replacement/flags`
command -range -nargs=* M :call SubstituteWithMatching(<q-args>, <line1>, <line2>)
":M/ inspired from eregex.vim
function SubstituteWithMatching(command, line1, line2)
let EscapeRegex={pattern->escape(pattern, '[]\')}
let openbracket ='([{'
let closebracket=')]}'
let nonbracketR='[^'.EscapeRegex(openbracket.closebracket).']'
let nonbracketsR=nonbracketR.'*'
let LiftLevel={pattern->
\nonbracketsR
\.'\%('
\.'['.EscapeRegex(openbracket).']'
\.pattern
\.'['.EscapeRegex(closebracket).']'
\.nonbracketsR
\.'\)*'
\}
let matchingR=LiftLevel(LiftLevel(LiftLevel(nonbracketsR)))
if v:false " optional test suite
echo "return 0:"
echo match('abc', '^'.matchingR.'$')
echo match('abc(ab)de', '^'.matchingR.'$')
echo match('abc(ab)d(e)f', '^'.matchingR.'$')
echo match('abc(a[x]b)d(e)f', '^'.matchingR.'$')
echo match('abc(a]b', '^'.matchingR.'$')
"current flaw (not a problem if there's only one type of bracket, or if
"the code is well-formed)
echo "return -1:"
echo match('abc(a(b', '^'.matchingR.'$')
echo match('abc)a(b', '^'.matchingR.'$')
endif
let [pattern, replacement, flags]=split(a:command, "/")
let pattern=substitute(pattern, '\\zm', EscapeRegex(matchingR), 'g')
execute a:line1.','.a:line2.'s/'.pattern.'/'.replacement.'/'.flags
endfunction
此后,:'<,'>M/array\[\(\zm\)\]\[\(\zm\)\]/get(\1, \2)/g
可用于执行上述相同的任务(在视觉模式下选择文本后)