当我搜索某些内容并捕获行号时如何检查行是否匹配?
How to check if line has match when I search something and catch the linenumber?
我想用 1 个或多个匹配项捕获缓冲区中的所有行号。
直到现在我都使用这个代码:
let lines = []
for line in range(startline, endline)
let @e = ''
:redir @e
:silent exe line.'s/'.mysearch.'/&/gne'
:redir END
if matchstr(@e, 'match') != ''
let nummer = matchstr(@e, '\d\+\ze')
if nummer > 0
call add(lines, ''.line.'')
endif
endif
endfor
但这速度太慢了。
有没有办法更快地做到这一点?
(p.e。静默执行搜索:1 表示匹配并捕获行号,0 表示不匹配)
这是一个可以做到这一点的函数:
function! GetLines(mysearch) range
let lines = []
let l:i=a:firstline
while l:i<=a:lastline
if matchstr(getline(l:i),a:mysearch) != ''
call add(lines, l:i)
endif
let l:i+=1
endwhile
let lines
endfunction
您可以通过以下方式调用它:
:N°1,N°2 call GetLines("pattern")
我会在 getline(1,'$')
上使用 filter()
。要获取行号,我们可以使用 map()
和新的 (Vim 8) lambda。或者可能只是 filter (range (1, line ('$')), 'getline (v:val) =~ regex')
您几乎找不到 vim 更快的方法,尤其是手动循环。
编辑:
例如,在一个 7850 行长的 vim 日志文件中搜索 "home"
,它出现了 6438 次:
echo lh#time#bench('filter', range (1, line ('$')), 'getline (v:val) =~ "home"')
需要 0.033297s
:echo lh#time#bench('filter', range (1, line ('$')),{ idx, val -> getline (val) =~ 'home'})[1]
需要 0.078506 秒——有点慢,但正则表达式更简单
let r=[]
+ echo = lh#time#bench('map', range(1, line('$')), 'substitute(getline(v:val), "home", "\=add(g:r, v:val)", "")')[1]
需要 8.841528 秒——我想这就是您使用手动循环得到的结果
:let start=reltime()|:let lines=filter(map(getline(1, '$'), {idx, val -> val =~ "home"?idx:0}), "v:val>0")|:echo reltimefloat(reltime(start, reltime()))
需要:0.075132s
顺便说一句,我还在我的 vim 8.0-134 上测量了之前的片段,match()
比普通的 [=21] 慢一点(不是很明显) =].不要问我为什么。
IOW,神秘的正则表达式似乎是最快的解决方案,当性能很重要时,应不惜一切代价避免手动循环。
我想用 1 个或多个匹配项捕获缓冲区中的所有行号。
直到现在我都使用这个代码:
let lines = []
for line in range(startline, endline)
let @e = ''
:redir @e
:silent exe line.'s/'.mysearch.'/&/gne'
:redir END
if matchstr(@e, 'match') != ''
let nummer = matchstr(@e, '\d\+\ze')
if nummer > 0
call add(lines, ''.line.'')
endif
endif
endfor
但这速度太慢了。
有没有办法更快地做到这一点?
(p.e。静默执行搜索:1 表示匹配并捕获行号,0 表示不匹配)
这是一个可以做到这一点的函数:
function! GetLines(mysearch) range
let lines = []
let l:i=a:firstline
while l:i<=a:lastline
if matchstr(getline(l:i),a:mysearch) != ''
call add(lines, l:i)
endif
let l:i+=1
endwhile
let lines
endfunction
您可以通过以下方式调用它:
:N°1,N°2 call GetLines("pattern")
我会在 getline(1,'$')
上使用 filter()
。要获取行号,我们可以使用 map()
和新的 (Vim 8) lambda。或者可能只是 filter (range (1, line ('$')), 'getline (v:val) =~ regex')
您几乎找不到 vim 更快的方法,尤其是手动循环。
编辑:
例如,在一个 7850 行长的 vim 日志文件中搜索 "home"
,它出现了 6438 次:
echo lh#time#bench('filter', range (1, line ('$')), 'getline (v:val) =~ "home"')
需要 0.033297s:echo lh#time#bench('filter', range (1, line ('$')),{ idx, val -> getline (val) =~ 'home'})[1]
需要 0.078506 秒——有点慢,但正则表达式更简单let r=[]
+echo = lh#time#bench('map', range(1, line('$')), 'substitute(getline(v:val), "home", "\=add(g:r, v:val)", "")')[1]
需要 8.841528 秒——我想这就是您使用手动循环得到的结果:let start=reltime()|:let lines=filter(map(getline(1, '$'), {idx, val -> val =~ "home"?idx:0}), "v:val>0")|:echo reltimefloat(reltime(start, reltime()))
需要:0.075132s
顺便说一句,我还在我的 vim 8.0-134 上测量了之前的片段,match()
比普通的 [=21] 慢一点(不是很明显) =].不要问我为什么。
IOW,神秘的正则表达式似乎是最快的解决方案,当性能很重要时,应不惜一切代价避免手动循环。