🏄

vim.regexを利用したstring.gmatch

2022/09/23に公開

NeovimのluaでVim形式の正規表現を使ってstring.gmatchのようにループを回したいときに。

string.vim_regex_gmatch = function(str, pattern)
  local vim_regex = vim.regex(pattern)
  local from_idx, to_idx = nil, nil
  return function()
    from_idx, to_idx = vim_regex:match_str(str)
    if from_idx == nil or to_idx == nil then
      return nil
    end
    local result = string.sub(str, from_idx + 1, to_idx)
    str = string.sub(str, to_idx + 1)
    return result
  end
end

'iskeyword'などを活用したいときに使える…かも。

なお正規表現としてバックスラッシュを渡す必要があるので、patternはバックスラッシュ自体をエスケープするか、[[]]リテラルを使用する必要があります。

local str = 'This-string contains sample_keyword. 42! これはサンプル文字列です。'
local pattern = '\\<.\\{-}\\>'
-- local pattern = [[\<.\{-}\>]]
for w in string.vim_regex_gmatch(str, pattern) do
  vim.pretty_print(w)
end

-- 表示結果(語句の区切りはiskeywordの設定により変わる)
-- "This"
-- "string"
-- "contains"
-- "sample_keyword"
-- "42"
-- "これは"
-- "サンプル"
-- "文字列"
-- "です"

Discussion