function! Reduce()
let ls=getpos("'<")
let lsp=ls[1]
let tvar = '\<' . @*
echom tvar
for i in range(1,30)
let ssv=getline(lsp+i-1)
let t1=matchstr(ssv,tvar)
echom t1
if t1 =~ @*
echom ssv
delete
endif
endfor
endfun
你可以用上面的脚本帮我吗?
这个脚本有什么问题..
如果我删除if条件,只需打印ssv。它用匹配打印所有30个字符串
但是当我把删除命令 - 它只匹配几个字符串。
尝试和验证相同的行为&#34;正常! DD&#34;取代&#34;删除&#34;命令也是如此。
答案 0 :(得分:2)
您在getline
循环中使用for
,i
作为相对行号。并删除循环中的行。这里发生的是:
line1
line2 <- i = 2
line3
line4
删除第2行:
line1
line3 <- i = 2
line4
然后for
循环增加i
:
line1
line3
line4 <- i = 3
所以下一个处理过的行是line4
,而不是您期望的line3
。
要解决从末尾到开头的删除行,即反向运行range
:
for i in range(30, 1, -1)
答案 1 :(得分:1)
正如phd所说,你需要改变你的迭代方向。
出于表演原因,我倾向于避免在这里使用循环。如果你有成千上万行(我知道,你只有30 ......),你就会发现它们有所不同。
我会这样写(如果我需要比:delete
更复杂的东西):
" untested
let first_line = line("'<")
" 1- extract all lines in the range
let lines= getline( first_line, first_line+30) " or 29 ?
" 2- convert lines into line numbers, or -1 if not matching
let matching_line_nrs = map(lines, 'match(v:val, tvar)>=0 ? v:key : -1')
" 3- keep the positive ones
call filter(matching_line_nrs, 'v:val > 0')
" 4- and finally remove the matching lines, in reserve order
" NB: I though there was a deleteline() function, but couldn't find any
" trace of it, hence execute(linenr.'delete')
call map(reverse(matching_line_nrs), 'execute(v:val."delete")')
与本机(并且效率极高)相比,这是非常复杂的
:exe "'<".',+29g/\<'.@*.'/d'
或者,以交互方式输入
:'<,+29g/\<^R*/d_
" With ^R being CTRL-R