閱讀126 返回首頁    go 阿裏雲 go 技術社區[雲棲]


Vim技能修煉教程(13) - 變量

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" --> Number 456
  • String "6bar" --> Number 6
  • String "foo" --> Number 0
  • String "0xf1" --> Number 241
  • String "0100" --> Number 64
  • String "0b101" --> Number 5
  • String "-8" --> Number -8
  • String "+8" --> Number 0

"foo"被轉換成0,和"+8"被轉換成0這兩條case要特殊注意。

另外,八進製"0100"的情況也要特別注意。
為了避免出現八進製轉換的問題,我們可以使用str2nr函數來做顯示轉換。因為str2nr默認是10進製的。

echo 0100

的結果為64

echo str2nr("0100")

的值為100.

真值和假值

在Vimscript中,0表示假值,其餘數值均表示真值。假值也可以用v:false表示,真值為v:true.

比如"foo"的值為假,因為"foo"轉換成整數的值是0.

列表類型

Vimscript的列表可以混雜各種元素。

例:

:let b:list1 = [1, 4.1e+3, "Hello",[1,2]]

列表可以用下標訪問。比如b:list1[0].
列表的下標從0開始計數。而[-1]表示最後一個元素。

如果要給列表元素一個不存在時的默認值的話,可以使用get()函數。

例:

        :echo get(mylist, idx)
        :echo get(mylist, idx, "NONE")

兩個列表可以通過+號來連接成一個列表:

        :let longlist = mylist + [5, 6]
        :let mylist += [7, 8]

子列表

Vimscript取子列表跟其它腳本語言很像,用[起始位置:結束位置]來進行切片。

        :let shortlist = mylist[2:-1]   " get List [3, "four"]

如果是從第一個元素開始,或者到最後一個元素結束,都可以省略:

        :let endlist = mylist[2:]       " from item 2 to the end: [3, "four"]
        :let shortlist = mylist[2:2]    " List with one item: [3]
        :let otherlist = mylist[:]      " make a copy of the List

如果越界了,也不會產生錯誤,到最後一個元素結束了就是了麼。

        :let mylist = [0, 1, 2, 3]
        :echo mylist[2:8]               " result: [2, 3]

列表的賦值和拷貝

如果將一個列表賦給另一個變量,不會複製列表,隻是傳遞引用。
如果想要複製一份列表的話,需要使用copy函數。
例:

        :let aa = [[1, 'a'], 2, 3]
        :let bb = copy(aa)
        :call add(aa, 4)
        :let aa[0][1] = 'aaa'
        :echo aa
        [[1, aaa], 2, 3, 4]
        :echo bb
        [[1, aaa], 2, 3]

但是請注意,copy隻是淺copy,如果有子列表,是隻複製引用的。如果真的要大搬家,需要使用deepcopy()函數。

列表的比較

  • is: 比較兩個變量是否引用同一列表
  • ==:比較兩個列表的值是否相等

另外需要注意的是,對於變量,會自動將字符串轉成數字,但是對於列表中的元素,沒有這種自動轉換。

        echo 4 == "4"
        1
        echo [4] == ["4"]
        0

列表的多變量賦值

如果要引用列表中的值,可以同時將其賦給多個變量。
例:

        :let [var1, var2; rest] = mylist

等價於:

        :let var1 = mylist[0]
        :let var2 = mylist[1]
        :let rest = mylist[2:]

這個對於函數返回值之類的是個利好。

列表的修改

對於可以定位的值,直接通過:let賦值的方式修改。

對於插入,添加,刪除等,使用相關函數來進行操作:

        :call insert(list, 'a')         " prepend item 'a'
        :call insert(list, 'a', 3)      " insert item 'a' before list[3]
        :call add(list, "new")          " append String item
        :call add(list, [1, 2])         " append a List as one new item
        :call extend(list, [1, 2])      " extend the list with two more items
        :let i = remove(list, 3)        " remove item 3
        :let l = remove(list, 3, -1)    " remove items 3 to last item
        :call filter(list, 'v:val !~ "x"')  " remove items with an 'x'

列表還可以排序、反轉和排重:

        :call sort(list)                " sort a list alphabetically
        :call reverse(list)             " reverse the order of items
        :call uniq(sort(list))          " sort and remove duplicates

使用for循環來處理列表

for循環是處理列表的最簡用手段:

        :for item in mylist
        :   call Doit(item)
        :endfor

for循環支持解構式的賦值:

        :for [i, j; rest] in listlist
        :   call Doit(i, j)
        :   if !empty(rest)
        :      echo "remainder: " . string(rest)
        :   endif
        :endfor

列表常用函數

  • empty函數:判空
  • len函數:計算列表元素個數
  • max函數:求列表最大元素
  • min函數:求列表最小元素
  • count函數:計算元素在列表中出現的次數
  • index函數:求元素第一次出現的位置
  • split函數:將字符串拆分成列表
  • join函數:將列表連接成一個字符串

字典

Vimscript的字典功能,其實就是哈希表。

例:

        :let mydict = {1: 'one', 2: 'two', 3: 'three'}
        :let emptydict = {}

訪問字典可以使用[]:

        :let val = mydict["one"]
        :let mydict["four"] = 4

在沒有歧義的情況下,也可以使用.:

        :let val = mydict.one
        :let mydict.four = 4

字典遍曆

可以通過遍曆keys列表和values列表的方式來遍曆字典。

例:

        :for key in keys(mydict)
        :   echo key . ': ' . mydict[key]
        :endfor
        :for v in values(mydict)
        :   echo "value: " . v
        :endfor

還可以遍曆前先排一次序:

        :for key in sort(keys(mydict))

也可以將key和value打包在一起,使用item函數遍曆:

        :for [key, value] in items(mydict)
        :   echo key . ': ' . value
        :endfor

字典的複製

字典的複製也同樣要使用copy和deepcopy函數。

字典的增刪改查

字典的修改和增加都很簡單,直接賦值就是了:

        :let dict[4] = "four"
        :let dict['one'] = item

最後更新:2017-07-14 18:02:25

  上一篇:go  【行業】透過雲計算、工業大數據對智能製造的一點思考
  下一篇:go  阿裏雲RDS金融數據庫(三節點版) - 性能篇