如何在 VimScript 中序列化一个变量?
How do I serialize a variable in VimScript?
我想保存一个随机 Vim 字典,比方说:
let dico = {'a' : [[1,2], [3]], 'b' : {'in': "str", 'out' : 51}}
到一个文件。有没有聪明的方法来做到这一点?我可以使用的东西,例如:
call SaveVariable(dico, "safe.vimData")
let recover = ReadVariable("safe.vimData")
或者我应该只用文本文件自己构建一些东西吗?
你可以好好利用:string()
功能。测试这些:
let g:dico = {'a' : [[1,2], [3]], 'b' : {'in': "str", 'out' : 51}}
let str_dico = 'let g:dico_copy = ' . string(dico)
echo str_dico
execute str_dico
echo g:dico_copy
... 这样您就可以将 str_dico 字符串保存为 vim 脚本文件的一行(例如使用 writefile()
) , 然后直接 source
vim 文件。
感谢 (干杯),我已经能够使用 string
、writefile
和 readfile
实现这些功能。这不是二进制序列化,但效果很好:)
function! SaveVariable(var, file)
" turn the var to a string that vimscript understands
let serialized = string(a:var)
" dump this string to a file
call writefile([serialized], a:file)
endfun
function! ReadVariable(file)
" retrieve string from the file
let serialized = readfile(a:file)[0]
" turn it back to a vimscript variable
execute "let result = " . serialized
return result
endfun
这样使用它们:
call SaveVariable(anyvar, "safe.vimData")
let restore = ReadVariable("safe.vimData")
尽情享受吧!
我在几年前写的脚本中使用了@iago-lito 的回答。昨天我花了一些时间改进它。 vim 字典与 JSON 对象非常相似,但是:
- 当我打开文件和
set filetype=json
时,linter 抱怨字符串周围的单引号,并且
- JSON 格式化程序将文本分成多行,并将它们缩进以制作一个漂亮的文件。因此,仅读取第 0 行文本并不能给出完整的字典对象。
这是我为解决这两个问题所做的修改。
function! SaveVariable(var, file)
" Change all single quotes to double quotes.
" {'x':'O''Toole','y':['A',2,'d']} -> {"x":"O""Toole","y":["A",2,"d"]}
let serialized = substitute(string(a:var),"'",'"','g')
" Change all escaped double quotes back to apostrophes.
" {"x":"O""Toole","y":["A",2,"d"]} -> {"x":"O'Toole","y":["A",2,"d"]}
let serialized = substitute(serialized,'""', "'",'g')
call writefile([serialized], a:file)
endfunction
function! ReadVariable(file)
execute 'let result = [' . join(readfile(a:file),'') . ']'
return result[0]
endfunction
这似乎适用于所有类型的数据。我用一个对象、一个列表以及数字和字符串标量值对其进行了测试。
陌生人,危险!
这是伴随此代码和任何其他动态生成的代码的警告词。 @iago-lito 和我的解决方案都容易受到代码注入的影响,如果您正在读取不受您控制的文件,您的机器可能会发生坏事。例如,如果有人将其偷偷放入文件中:
42|call system('rmdir /s /q c:\')|call system('rm -rf /')
调用@iago-lito 的 ReadVariable()
将 return 42,但您的计算机将是敬酒,无论是 Windows、Mac 还是 Linux 机器。我的版本也失败了,尽管声明的版本更复杂:
42]|call system('rmdir /s /q c:\')|call system('rm -rf /')|let x=[
一个合适的解决方案是解析文本,寻找实际数据的结尾,然后转储它后面的所有内容。这意味着您失去了这种方法的简单性。 Vim 和 Neovim 近年来取得了长足的进步。根据我的阅读,lua 和 python 比以往任何时候都更容易融入 vim脚本。如果这些语言中的任何一种都有这个问题的内置答案,我不会感到惊讶。
我想保存一个随机 Vim 字典,比方说:
let dico = {'a' : [[1,2], [3]], 'b' : {'in': "str", 'out' : 51}}
到一个文件。有没有聪明的方法来做到这一点?我可以使用的东西,例如:
call SaveVariable(dico, "safe.vimData")
let recover = ReadVariable("safe.vimData")
或者我应该只用文本文件自己构建一些东西吗?
你可以好好利用:string()
功能。测试这些:
let g:dico = {'a' : [[1,2], [3]], 'b' : {'in': "str", 'out' : 51}}
let str_dico = 'let g:dico_copy = ' . string(dico)
echo str_dico
execute str_dico
echo g:dico_copy
... 这样您就可以将 str_dico 字符串保存为 vim 脚本文件的一行(例如使用 writefile()
) , 然后直接 source
vim 文件。
感谢 string
、writefile
和 readfile
实现这些功能。这不是二进制序列化,但效果很好:)
function! SaveVariable(var, file)
" turn the var to a string that vimscript understands
let serialized = string(a:var)
" dump this string to a file
call writefile([serialized], a:file)
endfun
function! ReadVariable(file)
" retrieve string from the file
let serialized = readfile(a:file)[0]
" turn it back to a vimscript variable
execute "let result = " . serialized
return result
endfun
这样使用它们:
call SaveVariable(anyvar, "safe.vimData")
let restore = ReadVariable("safe.vimData")
尽情享受吧!
我在几年前写的脚本中使用了@iago-lito 的回答。昨天我花了一些时间改进它。 vim 字典与 JSON 对象非常相似,但是:
- 当我打开文件和
set filetype=json
时,linter 抱怨字符串周围的单引号,并且 - JSON 格式化程序将文本分成多行,并将它们缩进以制作一个漂亮的文件。因此,仅读取第 0 行文本并不能给出完整的字典对象。
这是我为解决这两个问题所做的修改。
function! SaveVariable(var, file)
" Change all single quotes to double quotes.
" {'x':'O''Toole','y':['A',2,'d']} -> {"x":"O""Toole","y":["A",2,"d"]}
let serialized = substitute(string(a:var),"'",'"','g')
" Change all escaped double quotes back to apostrophes.
" {"x":"O""Toole","y":["A",2,"d"]} -> {"x":"O'Toole","y":["A",2,"d"]}
let serialized = substitute(serialized,'""', "'",'g')
call writefile([serialized], a:file)
endfunction
function! ReadVariable(file)
execute 'let result = [' . join(readfile(a:file),'') . ']'
return result[0]
endfunction
这似乎适用于所有类型的数据。我用一个对象、一个列表以及数字和字符串标量值对其进行了测试。
陌生人,危险!
这是伴随此代码和任何其他动态生成的代码的警告词。 @iago-lito 和我的解决方案都容易受到代码注入的影响,如果您正在读取不受您控制的文件,您的机器可能会发生坏事。例如,如果有人将其偷偷放入文件中:
42|call system('rmdir /s /q c:\')|call system('rm -rf /')
调用@iago-lito 的 ReadVariable()
将 return 42,但您的计算机将是敬酒,无论是 Windows、Mac 还是 Linux 机器。我的版本也失败了,尽管声明的版本更复杂:
42]|call system('rmdir /s /q c:\')|call system('rm -rf /')|let x=[
一个合适的解决方案是解析文本,寻找实际数据的结尾,然后转储它后面的所有内容。这意味着您失去了这种方法的简单性。 Vim 和 Neovim 近年来取得了长足的进步。根据我的阅读,lua 和 python 比以往任何时候都更容易融入 vim脚本。如果这些语言中的任何一种都有这个问题的内置答案,我不会感到惊讶。