Vim技能修炼教程(13) - 变量
摘要:Vimscript的变量、列表和字典类型
VimScript变量
上节我们介绍了Python和Ruby来编写Vim插件的方式。
不过,Python和Ruby并不是所有的Vim都支持的功能,如果以最小依赖的原则来说,还是原汁原味的Vimscripts是放置四海Vim而皆灵的方式。当代码规模变大时,Python,Ruby,Perl这些语言的引入将带来较高的效率。但是Vimscripts仍然是最基本的Vim语言,值得我们首先学好。
变量
做为一种脚本语言,Vimscript当然是支持变量的。
不过Vimscript的特色是,显式指定作用域。也就是说,一个变量,需要在名字前加作用域前缀。
这些作用域前缀有:
b:缓冲区级作用域
w:窗口级作用域
t:标签页级作用域
g:全局变量
l:函数内局部变量
s:vim脚本文件级作用域
a:函数参数
v:Vim专用的全局变量
如果未指定前缀,定义于函数内部的默认为l:,而定义于函数之外的默认为g:.
Vimscript通过:let命令来为变量赋值,赋值之前不需要定义。
访问属性和寄存器
Vimscript通过&属性名的方式来访问属性,也就是除了:set之外,我们也可以通过:let为变量赋值。
同变量一样,属性也有作用域,可以通过&l:属性来只改本地属性。相当于我们使用了:setlocal命令。
:let还可以通过@来访问寄存器。
还记得吗?d,c,y等命令支持将删除或复制的内容放到寄存器中,如果未指定,则放入""寄存器中。"0到"9中最储历史值。还有"a到"z一共26个命名寄存器。
数据类型
首先是数据类型,Vimscript提供下面9种基本数据类型:
Number:32位带符号整数.如果支持+num64,就是64位带符号整数。支持十六进制,二进制和八进制。
Float:浮点数。只有编译时支持+float才有。
String:字符串。
List:有序列表。
Dictionary:哈希表。
Funcref:函数引用。
特殊值
v:false
v:true
v:none
v:null
Job:任务相关
Channel:通道相关
一个变量的类型可以通过type()函数查看。
数字和字符串
在Vimscript中,字符串和数字之间会进行自动转换。我们看下官方的几个例子:
String"456"-->Number456
String"6bar"-->Number6
String"foo"-->Number0
String"0xf1"-->Number241
String"0100"-->Number64
String"0b101"-->Number5
String"-8"-->Number-8
String"+8"-->Number0
"foo"被转换成0,和"+8"被转换成0这两条case要特殊注意。
另外,八进制"0100"的情况也要特别注意。
为了避免出现八进制转换的问题,我们可以使用str2nr函数来做显示转换。因为str2nr默认是10进制的。
echo0100
的结果为64
而
echostr2nr("0100")
的值为100.
真值和假值
在Vimscript中,0表示假值,其余数值均表示真值。假值也可以用v:false表示,真值为v:true.
比如"foo"的值为假,因为"foo"转换成整数的值是0.
列表类型
Vimscript的列表可以混杂各种元素。
例:
:letb:list1=[1,4.1e+3,"Hello",[1,2]]
列表可以用下标访问。比如b:list1[0].
列表的下标从0开始计数。而[-1]表示最后一个元素。
如果要给列表元素一个不存在时的默认值的话,可以使用get()函数。
例:
:echoget(mylist,idx)
:echoget(mylist,idx,"NONE")
两个列表可以通过+号来连接成一个列表:
:letlonglist=mylist+[5,6]
:letmylist+=[7,8]
子列表
Vimscript取子列表跟其它脚本语言很像,用[起始位置:结束位置]来进行切片。
:letshortlist=mylist[2:-1]"getList[3,"four"]
如果是从第一个元素开始,或者到最后一个元素结束,都可以省略:
:letendlist=mylist[2:]"fromitem2totheend:[3,"four"]
:letshortlist=mylist[2:2]"Listwithoneitem:[3]
:letotherlist=mylist[:]"makeacopyoftheList
如果越界了,也不会产生错误,到最后一个元素结束了就是了么。
:letmylist=[0,1,2,3]
:echomylist[2:8]"result:[2,3]
列表的赋值和拷贝
如果将一个列表赋给另一个变量,不会复制列表,只是传递引用。
如果想要复制一份列表的话,需要使用copy函数。
例:
:letaa=[[1,'a'],2,3]
:letbb=copy(aa)
:calladd(aa,4)
:letaa[0][1]='aaa'
:echoaa
[[1,aaa],2,3,4]
:echobb
[[1,aaa],2,3]
但是请注意,copy只是浅copy,如果有子列表,是只复制引用的。如果真的要大搬家,需要使用deepcopy()函数。
列表的比较
is:比较两个变量是否引用同一列表
==:比较两个列表的值是否相等
另外需要注意的是,对于变量,会自动将字符串转成数字,但是对于列表中的元素,没有这种自动转换。
echo4=="4"
1
echo[4]==["4"]
列表的多变量赋值
如果要引用列表中的值,可以同时将其赋给多个变量。
例:
:let[var1,var2;rest]=mylist
等价于:
:letvar1=mylist[0]
:letvar2=mylist[1]
:letrest=mylist[2:]
这个对于函数返回值之类的是个利好。
列表的修改
对于可以定位的值,直接通过:let赋值的方式修改。
对于插入,添加,删除等,使用相关函数来进行操作:
:callinsert(list,'a')"prependitem'a'
:callinsert(list,'a',3)"insertitem'a'beforelist[3]
:calladd(list,"new")"appendStringitem
:calladd(list,[1,2])"appendaListasonenewitem
:callextend(list,[1,2])"extendthelistwithtwomoreitems
:leti=remove(list,3)"removeitem3
:letl=remove(list,3,-1)"removeitems3tolastitem
:callfilter(list,'v:val!~"x"')"removeitemswithan'x'
列表还可以排序、反转和排重:
:callsort(list)"sortalistalphabetically
:callreverse(list)"reversetheorderofitems
:calluniq(sort(list))"sortandremoveduplicates
使用for循环来处理列表
for循环是处理列表的最简用手段:
:foriteminmylist
:callDoit(item)
:endfor
for循环支持解构式的赋值:
:for[i,j;rest]inlistlist
:callDoit(i,j)
:if!empty(rest)
:echo"remainder:".string(rest)
:endif
:endfor
列表常用函数
empty函数:判空
len函数:计算列表元素个数
max函数:求列表最大元素
min函数:求列表最小元素
count函数:计算元素在列表中出现的次数
index函数:求元素第一次出现的位置
split函数:将字符串拆分成列表
join函数:将列表连接成一个字符串
字典
Vimscript的字典功能,其实就是哈希表。
例:
:letmydict={1:'one',2:'two',3:'three'}
:letemptydict={}
访问字典可以使用[]:
:letval=mydict["one"]
:letmydict["four"]=4
在没有歧义的情况下,也可以使用.:
:letval=mydict.one
:letmydict.four=4
字典遍历
可以通过遍历keys列表和values列表的方式来遍历字典。
例:
:forkeyinkeys(mydict)
:echokey.':'.mydict[key]
:endfor
:forvinvalues(mydict)
:echo"value:".v
:endfor
还可以遍历前先排一次序:
:forkeyinsort(keys(mydict))
也可以将key和value打包在一起,使用item函数遍历:
:for[key,value]initems(mydict)
:echokey.':'.value
:endfor
字典的复制
字典的复制也同样要使用copy和deepcopy函数。
字典的增删改查
字典的修改和增加都很简单,直接赋值就是了:
:letdict[4]="four"
:letdict['one']=item
用云栖社区APP,舒服~