Zsh 開發指南(五): 陣列
導讀
瞭解完結構比較簡單的字串後,我們來看更復雜一些的陣列。其實字串在 zsh 中也可以當字元陣列操作,但很少有需要把字串當陣列來處理的場景。本篇中主要講的是字串陣列,複雜度要比單個字串高一些。
在實際的指令碼編寫中,較少需要處理單個的字串。往往需要處理從各個地方過來的大量文字,不可避免會用到陣列。用好陣列,會讓文字處理工作事半功倍。
本篇只涉及陣列的基礎用法。
陣列定義
陣列可以直接賦值使用,不需要提前宣告。等號和小括號之間不能有空格,小括號中的元素以空格隔開。
% array=(a bc ccc dddd)
# 用 $array 即可訪問陣列全部元素,輸出時元素以空格分隔
% echo $array
a bc ccc dddd
# 使用 print -l 可以每行輸出一個元素
% print -l $array
a
bc
ccc
dddd
# 輸出陣列中的元素個數,用法和取字串長度一樣
% echo $#array
4
# 包含帶空格的字串
% array=(a "bc ccc" dddd)
% print -l $array
a
bc ccc
dddd
# 可以換行賦值,但如果行中間有空格,依然需要加引號
% array=(
> a
> bb
> "c c c"
> dddd
> )
元素讀寫
% array=(a bc ccc dddd)
# 用法和取字串的第幾個字元一樣,從 1 開始算
% echo $array[3]
ccc
# -1 依然是最後一個元素,-2 是倒數第二個,以此類推
% echo $array[-1]
dddd
% array[3]=CCC
# 如果賦值的內容是一個空的小括號,則刪除該元素
% array[2]=()
% print -l $array
a
CCC
dddd
# 用 += 為陣列新增一個新元素
% array+=eeeee
% print -l $array
a
CCC
dddd
eeeee
# 用 unset 可以刪除整個陣列
% unset array
# array 變數變成未定義狀態
% echo $+array
0
陣列拼接
% array1=(a b c d)
% array2=(1 2 3 4)
# 用 += 拼接陣列
% array1+=(e f g)
% echo $array1
a b c d e f g
# 拼接另一個陣列,小括號不可以省略,否則 array1 會被轉成一個字串
% array2+=($array1)
% echo $#array2
11
# 去掉小擴號後,array1 被轉成了一個字串
% array2+=$array1
% echo $#array2
12
% echo $array2[12]
a b c d e f g
# 字串可以直接拼接陣列而轉化成陣列
% str=abcd
% str+=(1234)
% echo $#str
2
陣列遍歷
% array1=(a bb ccc dddd)
% array2=(1 2 3)
# 用 for 可以直接遍歷陣列,小括號不可省略
% for i ($array1) {
> echo $i
> }
a
bb
ccc
dddd
# 小括號裡可以放多個陣列,依次遍歷
% for i ($array1 $array2) {
> echo $i
> }
a
bb
ccc
dddd
1
2
3
陣列切片
陣列切片和字串切片操作方法完全相同。
% array=(a bb ccc dddd)
% echo $array[2,3]
bb ccc
# 依然可以多對多地替換元素
% array[3,-1]=(1 2 3 4)
% echo $array
a bb 1 2 3 4
# 也可以使用另一種語法,不建議使用
% echo ${array:0:3}
a bb 1
元素查詢
陣列的元素查詢方法,和字串的子字串查詢語法一樣。
% array=(a bb ccc dddd ccc)
# 用小 i 輸出從左到右第一次匹配到的元素位置
% echo $array[(i)ccc]
3
# 如果找不到,返回陣列大小 + 1
% echo $array[(i)xxx]
6
# 用大 I 輸出從右到左第一次匹配到的元素位置
% echo $array[(I)ccc]
5
# 如果找不到,返回 0
% echo $array[(I)xxx]
0
# 可以用大 I 判斷是否存在元素
% (($array[(I)dddd])) && echo good
good
% (($array[(I)xxx])) && echo good
% array=(aaa bbb aab bbc)
# n:2: 從指定的位置開始查詢
% echo ${array[(in:2:)aa*]}
3
元素排序
% array=(aa CCC b DD e 000 AA 3 aa 22)
# 用小寫字母 o 升序排列,從小到大
% echo ${(o)array}
000 22 3 aa aa AA b CCC DD e
# 用大寫字母 O 降序排列,從大到小
% echo ${(O)array}
e DD CCC b AA aa aa 3 22 000
# 加 i 的話大小寫不敏感
% echo ${(oi)array}
000 22 3 aa AA aa b CCC DD e
% array=(cc aaa b 12 115 90)
# 加 n 的話按數字大小順序排
% echo ${(on)array}
12 90 115 aaa b cc
# Oa 用於反轉陣列元素的排列順序
% echo ${(Oa)array}
90 115 12 b aaa cc
去除重複元素
% array=(ddd a bb a ccc bb ddd)
% echo ${(u)array}
ddd a bb ccc
使用連續字元或者數值構造陣列
# 大括號中的逗號分隔的字串會被展開
% array=(aa{bb,cc,11}) && echo $array
aabb aacc aa11
# .. 會將前後的陣列連續展開
% array=(aa{1..3}) && echo $array
aa1 aa2 aa3
# 第二個 .. 後的數字是展開的間隔
% array=(aa{15..19..2}) && echo $array
aa15 aa17 aa19
# 也可以從大到小展開
% array=(aa{19..15..2}) && echo $array
aa19 aa17 aa15
# 可以新增一個或多個前導 0
% array=(aa{01..03}) && echo $array
aa01 aa02 aa03
# 單個字母也可以像數值那樣展開,多個字母不行
% array=(aa{a..c}) && echo $array
aaa aab aac
# 字母是按 ASCII 碼的順序展開的
% array=(aa{Y..c}) && echo $array
aaY aaZ aa[ aa\ aa] aa^ aa_ aa` aaa aab aac
# 這些用法都可以用在 for 迴圈裡邊
% for i (aa{a..c}) {
> echo $i
> }
aaa
aab
aac
從字串構造陣列
% str="a bb ccc dddd"
# ${=str} 可以將 str 內容按空格切分成陣列
% array=(${=str})
% print -l $array[2,3]
bb
ccc
% str="a:bb:ccc:dddd"
# 如果是其他分隔符,可以設定 IFS 環境變數指定
% IFS=:
% array=(${=str})
% print -l $array[2,3]
bb
ccc
% str="a\nbb\nccc\ndddd"
# 如果是其他分隔符,也可以用 (s:x:) 指定
% array=(${(s:\n:)str})
% print -l $array[2,3]
bb
ccc
% str="a##bb##ccc##dddd"
# 分隔符可以是多個字元
% array=(${(s:##:)str})
% print -l $array[2,3]
bb
ccc
% str="a:bb:ccc:dddd"
# 如果分隔符是 :,可以 (s.:.)
% array=(${(s.:.)str})
% print -l $array[2,3]
bb
ccc
從檔案構造陣列
test.txt
內容。
a
bb
ccc
dddd
每行一個元素。
# f 的功能是將字串以換行符分隔成陣列
# 雙引號不可省略,不然會變成一個字串,引號也可以加在 ${ } 上
% array=(${(f)"$(<test.txt)"})
% print -l $array
a
bb
ccc
dddd
# 不加引號的效果
% array=(${(f)$(<test.txt)})
% print -l $array
a bb ccc dddd
# 從檔案構造陣列,並將每行按分隔符 : 分隔後輸出所有列
for i (${(f)"$(<test.txt)"}) {
array=(${(s.:.)i})
echo $array[1,-1]
}
從檔案列表構造陣列
# 這裡的 * 即上一篇講的萬用字元,所有的用法都可以在這裡使用。
% array=(/usr/bin/vim*)
% print -l $array
/usr/bin/vim
/usr/bin/vimdiff
/usr/bin/vimtutor
# 要比 ls /usr/bin/[a-b]?? | wc -l 快很多
% array=(/usr/bin/[a-b]??) && print $#array
3
陣列交集差集
% array1=(1 2 3)
% array2=(1 2 4)
# 兩個陣列的交集,只輸出兩個陣列都有的元素
% echo ${array1:*array2}
1 2
# 兩個陣列的差集,只輸出 array1 中有,而 array2 中沒有的元素
% echo ${array1:|array2}
3
# 如果有重複元素,不會去重
% array1=(1 1 2 3 3)
% array2=(4 4 1 1 2 2)
% echo ${array1:*array2}
1 1 2
陣列交叉合併
% array1=(a b c d)
% array2=(1 2 3)
# 從 array1 取一個,再從 array2 取一個,以此類推,一個陣列取完了就結束
% echo ${array1:^array2}
a 1 b 2 c 3
# 如果用 :^^,只有一個陣列取完了的話,繼續從頭取,直到第二個陣列也取完了
% echo ${array1:^^array2}
a 1 b 2 c 3 d 1
對陣列中的字串進行統一的處理
一些處理字串的方法(主要是各種形式的擷取、替換、轉換等等),也可以用在陣列上,效果是對陣列中所有元素統一處理。
% array=(/a/b.htm /a/c /a/b/c.txt)
# :t 是取字串中的檔名,可以用在陣列上,取所有元素的檔名
% print -l ${array:t}
b.htm
c
c.txt
# :e 是取副檔名,如果沒有沒有副檔名,結果陣列中不會新增空字串
% print -l ${array:e}
htm
txt
# 字串替換等操作也可以對陣列使用,替換所有字串
% print -l ${array/a/j}
/j/b.txt
/j/c
/j/b/c.txt
:#
也可以在陣列上用,但更實用一些。
% array=(aaa bbb ccc)
# :# 是排除匹配到的元素,類似 grep -v
% print ${array:#a*}
bbb ccc
# 前邊加 (M),是反轉後邊的效果,即只輸出匹配到的元素,類似 grep
% print ${(M)array:#a*}
aaa
# 多個操作可以同時進行,(U) 是把字串轉成大寫字母
% print ${(UM)array:#a*}
AAA
總結
本篇講的是陣列的基礎用法,還有很多複雜的操作方法,以後會提到。
參考
http://zshwiki.org/home/scripting/array
http://www.bash2zsh.com/zsh_refcard/refcard.pdf
更新歷史
20170830:增加“使用連續字元或者數值構造陣列”。
20170909:修正“從字串構造陣列”中的錯誤。
20170910:增加“從字串構造陣列”中的部分內容。
相關文章
- Zsh 開發指南(第五篇 陣列)陣列
- JNI/NDK開發指南(5):訪問陣列(基本型別陣列與物件陣列)陣列型別物件
- Zsh 開發指南(第十二篇 [[ ]] 的用法)
- Zsh 開發指南(第十三篇 管道和重定向)
- Zsh 開發指南(第十四篇 檔案讀寫)
- Zsh 開發指南(四): 字串處理之萬用字元字串字元
- iOS開發中陣列常用的五種遍歷方式iOS陣列
- Zsh 開發指南(第十六篇 alias 和 eval 的用法)
- Zsh 開發指南(第七篇 數值計算)
- Zsh 開發指南(第十五篇 程式與作業控制)
- Zsh 開發指南(第二篇 字串處理之常用操作)字串
- Zsh 開發指南(第一篇 變數和語句)變數
- Zsh 開發指南(第十一篇 變數的進階內容)變數
- JavaScript權威指南-陣列JavaScript陣列
- JavaScript 陣列方法:綜合指南JavaScript陣列
- JavaScript基礎(五)陣列JavaScript陣列
- JavaScript權威指南(7)——陣列JavaScript陣列
- Go 快速入門指南 - 陣列Go陣列
- zsh+on-my-zsh配置教程指南(程式設計師必備)程式設計師
- zsh終端下如何用命令列開啟sublime命令列
- 第五章 陣列Ivor Horton陣列
- 大資料開發-Go-陣列,切片大資料Go陣列
- 第五章 陣列程式(Ivor Horton)陣列
- iOS開發·必會的演算法操作:字串陣列排序+模型物件陣列排序iOS演算法字串陣列排序模型物件
- Zsh 開發指南(第十七篇 使用 socket 檔案和 TCP 實現程式間通訊)TCP
- PHP開發之自定義函式及陣列PHP函式陣列
- iOS專案開發實戰——plist陣列解析iOS陣列
- iOS開發系列--C語言之陣列和字串iOSC語言陣列字串
- 無水乾貨:Java陣列優秀指南Java陣列
- 五分鐘快速瞭解ArrayLike(類陣列)陣列
- Perl學習筆記(五)——關聯陣列筆記陣列
- Zsh 開發指南(第三篇 字串處理之轉義字元和格式化輸出)字串字元
- PHP 開發工程師基礎篇 (PHP 陣列)PHP工程師陣列
- 開發指南
- Java 陣列最佳指南,快收藏讓它吃灰Java陣列
- 飛機的 PHP 學習筆記五:陣列PHP筆記陣列
- 安裝oh-my-zsh(命令列工具)命令列
- JavaSE 陣列:一維陣列&二維陣列Java陣列