Search 当我搜索某物并捕获行号时,如何检查行是否匹配?
我希望捕获缓冲区中具有1个或多个匹配项的所有行号 到目前为止,我使用的代码是:Search 当我搜索某物并捕获行号时,如何检查行是否匹配?,search,vim,match,buffer,lines,Search,Vim,Match,Buffer,Lines,我希望捕获缓冲区中具有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
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
但这是难以置信的慢。没有办法更快地做到这一点吗?
(即,静默执行搜索: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
这里有一个函数可以做到这一点:
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
我会在getline(1,“$”)
上使用filter()
。要获得行号,我们可以使用map()
和新的(Vim 8)lambdas。或者可以是简单的过滤器(范围(1,行(“$”),“getline(v:val)=~regex”)
使用vim,您几乎找不到任何更快的方法,尤其是手动循环
编辑:
例如,在7850行长的vim日志文件上搜索“home”
,搜索次数为6438次:
需要0.033297secho lh#time#bench('filter',range(1,line('$')),'getline(v:val)=~“home”)
需要0.078506s——稍微慢一点,但正则表达式更简单:echo lh#time#bench('filter',range(1,line('$),{idx,val->getline(val)=~'home'})[1]
+让r=[]
需要8.841528秒——我想这就是手动循环的结果echo=lh#time#bench('map',range(1,line('$),'substitute(getline(v:val),“home”,“\\=add(g:r,v:val)”,”)[1]
:let start=reltime()
match()
比普通的=~
慢了一点(实际上感觉不到)。别问我为什么
总之,神秘的正则表达式似乎是最快的解决方案,当性能很重要时,应该不惜一切代价避免手动循环。我会在getline(1,“$”)上使用filter()
。要获得行号,我们可以使用map()
和新的(Vim 8)lambdas。或者可以是简单的过滤器(范围(1,行(“$”),“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.078506s——稍微慢一点,但正则表达式更简单
让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()
顺便说一句,我在我的vim 8.0-134之前的代码片段中也测量到,match()
比普通的=~
慢了一点(实际上感觉不到)。别问我为什么
看来,神秘的正则表达式似乎是最快的解决方案,当性能很重要时,应该不惜一切代价避免手动循环。你能解释一下你想用这些代码做什么吗?@Meninx-メネンックス, 你好,梅尼恩。。我想用搜索中的匹配项捕获缓冲区中的所有行号。。。p、 e.搜索是exe 1s/foo/&/gne
如果第1行中有“foo”,它会给出一个匹配项,我想将第1行放入我的列表行中。如果第1行中没有“foo”,那么就不需要在第1行中插入任何内容。你能解释一下你想用这些代码做什么吗?@Meninx-メネンックス, 你好,梅尼恩。。我想用搜索中的匹配项捕获缓冲区中的所有行号。。。p、 e.搜索是exe 1s/foo/&/gne
如果第1行中有“foo”,它会给出一个匹配项,我想将第1行放入我的列表行中。如果第1行中没有“foo”,则无需在第1行中插入任何内容。谢谢Luc<代码>过滤器(范围(1,行(“$”),“getline(v:val)=~regex”)
-->不是编辑器命令。它似乎不是一个编辑器命令。我做错什么了吗?正则表达式必须是搜索词,不是吗?使用matchstr()
。找到它。只需分配它(linenrs=)。这是一个伟大的解决方案!我发现的唯一问题是我经常在正则表达式中使用单引号和双引号。它与您正在使用的引号冲突。如果您在筛选器或映射中硬编码正则表达式,则必须使用双引号。相反,您可以将表达式存储到变量中。或者您也可以使用vim 8中的新lambda功能。如有疑问,:h filter()
,:h map()
,:h lambda
(IIRC)感谢Luc<代码>过滤器(范围(1,行(“$”),“getline(v:val)=~regex”)
-->不是编辑器命令。它似乎不是一个编辑器命令。我做错什么了吗?正则表达式必须是搜索词,不是吗?使用matchstr()
。找到它。只需分配它(linenrs=)。这是一个伟大的解决方案!我发现的唯一问题是我经常在正则表达式中使用单引号和双引号。它与您正在使用的引号冲突。如果您在筛选器或映射中硬编码正则表达式,则必须使用双引号。相反,您可以将表达式存储到变量中。或者您也可以使用vim 8的新lambda功能。如有疑问,:h filter()
,:h map()
,:h lambda
(IIRC)非常感谢您的解决方案!这似乎效果很好,但比我在问题中所写的解决方案快不了多少。一点问题都没有非常感谢你