如何从 vimscript 中的整个文件中搜索令牌?

How can I get a token from a search in a whole file in vimscript?

之前可能有人问过这个问题,但我在 google...

上找不到答案
  1. search函数查看缓冲区中的整个文件,但只有return匹配的行号。

  2. matchstr 函数可以 return 一个标记,但只查看一个给定的字符串。

如何实现结合两者的功能,在整个文件中搜索得到token?有没有简单的解决办法?

有几种可能:

选项A

您可以使用 searchpos() 获取匹配项的行号和起始列,然后使用 getline() 并通过 matchstr() 获取匹配项,使用列作为 {start} 参数(以正确处理一行中的多个匹配项)。

选项 B

两次使用searchpos(),第二次使用ceW参数得到匹配结束。现在您有两个位置,您可以为两个位置都设置标记,然后在它们之间拉出文本,或者使用 getline()strpart().

选项 C

我的 ingo-library plugin 有一个 ingo#text#frompattern#Get( firstLine, lastLine, pattern, replacement, isOnlyFirstMatch, isUnique ) 函数可以提取这样的匹配项。

在 Vim 的最新版本(7.3.610 及更高版本)中,您可以(ab)使用 Vim 的正常模式搜索对象 "gn" 来执行此操作。

首先,将"last search"寄存器设置为你想要的模式:

let @/='my pattern'

接下来,转到文件的开头,然后拉出下一个搜索结果:

normal! ggygn

现在,搜索文本在寄存器中 @0

如果你想使用不同的寄存器,你也可以这样做:

normal! gg"aygn

现在在注册中@a

注意,所有这些都会破坏搜索和其他寄存器,因此保存和恢复这些寄存器是有礼貌的。类似于:

function MyGetSearch(pattern)
  let oldpat=@/
  let @/=a:pattern
  let old_a=@a
  normal! gg"aygn
  let result=@a
  let @a=old_a
  let @/=oldpat
  return result
endfun

你可以更疯狂地使用这个,恢复光标位置等等,但这是基本的想法。

另一种选择是将文件的内容转换为字符串,然后将其作为 matchstr()expr 参数传递:

  //get a list containing all lines in the file as items:
let lineList = readfile(<filename>)
  //join the lines into a single string using "\n" or your preferred line delimiter:
let fileString = join(lineList, "\n")
  //search fileString for your pattern:
let matchedText = matchstr(fileString, <pattern to match>)

readfile() join() matchstr()

奖励:如果您想使用当前缓冲区而不是任意文件执行此操作,您可以将对 readfile() 的调用替换为 getline(1,'$') 以获取包含当前缓冲区所有行的列表缓冲区。