迭代Vimscript中的字符串或解析JSON文件

时间:2013-07-19 16:34:55

标签: json string parsing vim

所以我正在创建一个vim脚本,需要将JSON文件加载并解析为本地对象图。我搜索过,我找不到任何本地方式来处理JSON文件,我不想在脚本中添加任何依赖项。所以我编写了自己的函数来解析JSON字符串(从文件中获取),但它确实很慢。目前,我遍历文件中的每个字符,如下所示:

let len = strlen(jsonString) - 1
let i = 0
while i < len
    let c = strpart(jsonString, i, 1)
    let i += 1
    " A lot of code to process file....
    " Note: I've tried short cutting the process by searching for enclosing double-quotes when I come across the initial double quotes (also taking into account escaping '\' character.  It doesn't help
endwhile

我也尝试过这种方法:

for c in split(jsonString, '\zs')
    " Do a lot of parsing ....
endfor

作为参考,具有~29,000个字符的文件需要大约4秒来处理,这是不可接受的。

有没有更好的方法在vim脚本中迭代字符串?

或者更好的是,我是否错过了解析JSON的本机函数?

更新

我没有依赖,因为我:

  1. 不想与他们打交道
  2. 真正想要一些想法,以便在没有别人的工作的情况下做到这一点。
  3. 有时我只是想手动做事,即使问题已经解决了。
  4. 我根本不反对插件或依赖,只是我很好奇。因此问题。

    我最终创建了自己的函数来解析JSON文件。我正在创建一个可以解析与node.js模块关联的package.json文件的脚本。因此,我可以依赖相当一致的格式,并在我检索到所需信息时退出处理。这通常会删除文件的大块,因为大多数开发人员最后放置文件的最大块,即“自述”部分。因为package.json文件是严格定义的,所以我让这个过程有些脆弱。它假设了一个根字典{ }并主动查找某些条目。您可以在此处找到该脚本:https://github.com/ahayman/vim-nodejs-complete/blob/master/after/ftplugin/javascript.vim#L33

    当然,这不能回答我自己的问题。这只是我独特问题的解决方案。我会等几天寻找新的答案并在赏金结束前选择最好的答案(已经在我的手机上设置了闹钟)。

3 个答案:

答案 0 :(得分:3)

尽管Vim的起源可以追溯到很多,但它的内部字符串()eval()表示接近JSON,它可能会起作用,除非你需要特殊的字符。

如果需要,您可以在此处查找甚至支持true / false / null的实现: https://github.com/MarcWeber/vim-addon-json-encoding

更好地使用该库(vim-addon-manager允许轻松安装依赖项)。 现在,这取决于您的数据是否足够好。

现在Benjamin Klein将您的问题发布到vim_use,这就是我回复的原因。 如果您订阅Vim邮件列表,则会发生最佳和快速的回​​复。 转到vim.sf.net并按照社区链接。 你不能指望Vim社区刮掉stackoverflow。

我已将关键字“json”和“解析”添加到可以更容易找到的小代码中。

如果此解决方案不适合您,您可以尝试以下方法:h if_ *绑定或编写提取您正在查找的信息的外部脚本,或将JSON转换为Vim的字典表示形式,可以通过eval读取(逃避你正确关心的特殊字符。

答案 1 :(得分:2)

如果您寻求完全正确的解决方案,省略依赖关系是您可以做的最糟糕的事情之一。 @MarcWeber提到的eval()变体是最快的变种之一,但它有其缺点:

  1. 使用我在评论中提到的solution for securing eval使其不再是最快的。事实上,在你使用它之后,它会使eval()慢一个数量级(在我的测试中为0.02s vs 0.53s)。
  2. 它不尊重代理人对。
  3. 它不能用于验证您是否具有正确的JSON:它接受一些不是JSON字符串的字符串(例如"\<C-o>")并允许使用尾随逗号。
  4. 无法提供正常的错误消息。如果您使用我在第1页中提到的vam#VerifyIsJSON,它会失败。
  5. 无法加载1e10之类的浮点值(vim需要数字看起来像1.0e10,但数字如1e10 are allowed:注意第一段中的“和/或”
  6. 。以上所有(第一个除外)语句也适用于@MarcWeber提到的vim-addon-json-encoding,因为它使用了eval。还有其他一些可能性:

    1. 最快,最正确的是使用python:pyeval('json.loads(vim.eval("varname"))')。不比eval快,但在其他可能性中最快。 (在我的测试中为0.04:比eval()慢大约两倍)

      请注意,我在这里使用pyeval()。如果您想要缺少此功能的vim版本的解决方案,它将不再是最快的解决方案之一。

    2. 使用我的json.vim插件。与失败的vam#VerifyIsJSON相比,它具有稍微好一点的错误报告优势,与eval()相比略差,并且正确加载了浮点数。它可用于验证字符串(它不接受"\<C-a>"),但它加载带尾随逗号的列表就好了。它不支持代理对。它也很慢:在我使用的测试中(它使用279702个字符长字符串)需要11.59秒才能加载。尽管如此,Json.vim尝试使用python。
    3. 为了获得最佳错误报告,您可以使用yaml.vim并清除YAML支持,只留下JSON(我曾经为pyyaml做过同样的事情,但在python中:请参阅markedjson library used in powerline:它是pyyaml减去YAML的东西加上带标记的类)。但是这个变体甚至比json.vim慢,只有当你需要的主要内容是错误报告时才应该使用:加载相同的279702字符长字符串需要207秒。
    4. 请注意,提到的唯一满足“无依赖性”和“无python”要求的变体是eval()。如果你的劣势不好,就必须抛弃其中一个或两个要求。或者复制粘贴代码。虽然如果你考虑速度只剩下两个候选人:eval()和python:如果你想快速解析json,你真的必须使用C,只有这些解决方案花费大部分时间在用C编写的函数中。

      大多数其他解释器(ruby / perl / TCL)没有pyeval()等价,因此即使他们的JSON实现是用C编写的,它们也会慢一些。其他一些(lua / racket(mzscheme))有{{ 1}}等价,但是例如pyeval()为零意味着您必须显式添加其他步骤并递归地将对象转换为vim词典和列表(例如luaeval('{}')),这将影响性能。关于luaeval('vim.dict({})')不能说什么,但我从来没有听说过任何人实际上在vim上使用球拍(mzscheme)。

答案 2 :(得分:1)

依赖性最小的最简单的解决方案就是使用json_decode vim函数。

let dict = json_docde(jsonString)