[英]In Vim, is there a “matching braces/parenthesis/etc” equivalent in substitute/search symbols?
例如,我想用括號內的換行符(可能有空格、其他括號打開和關閉等)以外的任何內容替換“foo{...}”的每次出現,而不是后跟“bar”。
例如,“foo{{ }}, bar”中的“foo{{ }}”會匹配,但不會匹配“foo{hello{}}bar”。
我試過/foo{.*}\\(bar\\)\\@!
和/foo{.\\{-}}\\(bar\\)\\@!
但第一個將匹配“foo{}bar{}”,第二個將匹配“foo{{}}bar”(僅“foo{{}”部分)。
這個正則表達式:
foo{.*}\([}]*bar\)\@!
火柴:
foo{{ }}
foo{{ }}, bar
但不是:
foo{hello{}}bar
使用正則表達式不可能正確匹配任意級別的嵌套括號。 但是,可以構建一個正則表達式來匹配支持有限數量的嵌套(我認為這個答案沒有嘗試這樣做)。 – 本
這確實...
最多一層內大括號:
/foo{[^{}]*\({[^{}]*}[^{}]*\)*}\(bar\)\@!
最多兩層內大括號:
/foo{[^{}]*\({[^{}]*\({[^{}]*}[^{}]*\)*}[^{}]*\)*}\(bar\)\@!
最多三個級別的內括號:
/foo{[^{}]*\({[^{}]*\({[^{}]*\({[^{}]*}[^{}]*\)*}[^{}]*\)*}[^{}]*\)*}\(bar\)\@!
...
取決於您想要准確執行的替換,您可能可以使用宏來做到這一點。
例如:鑒於此文本
line 1 -- -- -- -- array[a][b[1]]
line 2 -- array[c][d]
line 3 -- -- -- -- -- -- -- array[e[0]][f] + array[g[0]][h[0]]
用get(A, B)
替換array[A][B]
。
要做到這一點:
/array<cr>
qq
開始錄制宏%
轉到匹配的括號,並使用一些 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
可以用來做同樣的事情上面的任務(在視覺模式下選擇文本后)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.