Search 当我搜索某物并捕获行号时,如何检查行是否匹配?

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

我希望捕获缓冲区中具有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
但这是难以置信的慢。
没有办法更快地做到这一点吗?

(即,静默执行搜索: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次:

  • 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()
比普通的
=~
慢了一点(实际上感觉不到)。别问我为什么

总之,神秘的正则表达式似乎是最快的解决方案,当性能很重要时,应该不惜一切代价避免手动循环。

我会在
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)非常感谢您的解决方案!这似乎效果很好,但比我在问题中所写的解决方案快不了多少。一点问题都没有非常感谢你