Shell 數(shù)組
1. Shell 數(shù)組概述
我們學(xué)習(xí)了變量,知道了變量為存儲(chǔ)單個(gè)元素的最小單元,本節(jié)我們來學(xué)習(xí)數(shù)組來存放多個(gè)元素的集合。
1.1 Shell 數(shù)組是什么
顧名思義,數(shù)組就是一系列數(shù)據(jù)的集合,這個(gè)數(shù)據(jù)就是我們之前學(xué)習(xí)的存儲(chǔ)單個(gè)元素的最小單元變量,也就是說將一些列的元素整合到一個(gè)集合內(nèi),這個(gè)集合的名稱就叫數(shù)組。當(dāng)然與其他語言一樣,數(shù)組具備幾個(gè)條件,在 Shell 中數(shù)組僅支持一維數(shù)組,數(shù)組元素的下標(biāo)從 0 開始,數(shù)組元素沒有最大限制等。
1.2 為什么要用數(shù)組
與變量類似,當(dāng)我們操作批量數(shù)據(jù)的時(shí)候,一個(gè)一個(gè)變量操作非常不便,此時(shí)我們可以使用一個(gè)數(shù)組集合,對整個(gè)數(shù)組集合進(jìn)行遍歷或其他操作,最終實(shí)現(xiàn)批量的效果,數(shù)組使得我們的腳本更具擴(kuò)展性。
1.3 變量與數(shù)組的差異
變量是存儲(chǔ)單個(gè)數(shù)據(jù)的單元,其在內(nèi)存中是隨機(jī)存儲(chǔ)的,數(shù)組是存儲(chǔ)一系列數(shù)據(jù)的集合,是事先在內(nèi)存中開辟連續(xù)的一系列空間,之后將數(shù)組元素有序的存儲(chǔ)在其中。
2. 數(shù)組的基本使用
2.1 數(shù)組的定義
數(shù)組的定義有兩種方式,可分為直接定義和單元素定義。
2.1.1 直接定義
數(shù)組類似于變量定義,只不過將里面的值用小括號括起來,其中每個(gè)元素使用空格分割。Shell 是弱類型的,數(shù)組中元素的類型可以不一樣,例如其中可以包含數(shù)字與字符串。
例如:
ARG1=(1 2 3 "hello Shell")
ARG1
為數(shù)組名稱,其值前三個(gè)為數(shù)字,最后一個(gè)為字符串。
2.1.2 單元素定義
Shell 中數(shù)組下標(biāo)從 0 開始,利用單個(gè)元素來定義數(shù)組。
例如:
[root@master scripts]# ARG2[0]=1
[root@master scripts]# ARG2[1]=2
[root@master scripts]# ARG2[2]=3
[root@master scripts]# ARG2[3]="hello Shell"
2.2 元素獲取
2.2.1 獲取單個(gè)元素
與變量的引用一樣,數(shù)組可以獲取單個(gè)位置的元素,利用 ${ARG[num]}
。
例如:
[root@master scripts]# echo ${ARG1[0]} //獲取AEG1數(shù)組中第一個(gè)元素
1
[root@master scripts]# echo ${ARG1[3]} //獲取AEG1數(shù)組中第四個(gè)元素
hello Shell
2.2.2 獲取全部元素
- 獲取數(shù)組值
獲取數(shù)組全部元素使用 ${ARG[*]}
或 ${ARG[@]}
。
例如:
[root@master scripts]# echo ${ARG1[@]}
1 2 3 hello Shell
[root@master scripts]# echo ${ARG1[*]}
1 2 3 hello Shell
- 獲取數(shù)組下標(biāo)
獲取數(shù)組全部下標(biāo)使用 ${!ARG[*]}
或 ${!ARG[@]}
。
例如:
[root@master ~]# echo ${!ARG1[@]}
0 1 2 3
[root@master ~]# echo ${!ARG1[*]}
0 1 2 3
2.2.3 獲取數(shù)組長度
- 獲取整個(gè)數(shù)組長度
數(shù)組長度及數(shù)組中元素的個(gè)數(shù),可以利用 ${#ARG[*]}
或 ${#ARG[@]}
,我們發(fā)現(xiàn)其實(shí)就是在獲取數(shù)組全部元素前添加#
來獲取數(shù)組個(gè)數(shù)。
例如:
[root@master scripts]# echo ${#ARG1[*]}
4
[root@master scripts]# echo ${#ARG1[@]}
4
- 獲取單個(gè)元素的長度
對于數(shù)組中的某個(gè)元我們也可以進(jìn)行長度的獲取,可以利用 ${#ARG1[num]}
。
例如:
[root@master scripts]# echo ${ARG1[@]}
100 2 3 hello Shell 10
[root@master scripts]# echo ${ARG1[3]} //獲取第四個(gè)元素內(nèi)容為:hello Shell
hello Shell
[root@master scripts]# echo ${#ARG1[3]} //獲取四個(gè)元素長度為11
11
2.2.4 數(shù)組元素的修改
數(shù)組可以進(jìn)行一些列對其元素的操作。
- 修改
對數(shù)組元素的修改,直接對單個(gè)元素修改即可,例如:
[root@master scripts]# AEG1[0]=100
[root@master scripts]# echo ${ARG1[@]}
100 2 3 hello Shell
- 增加
對數(shù)組元素的增加,和修改一致,直接對單個(gè)位置元素增加即可,例如:
[root@master scripts]# ARG1[10]=10
[root@master scripts]# echo ${ARG1[@]}
100 2 3 hello Shell 10
[root@master scripts]# echo ${#ARG1[@]}
5
Tips:在此我們發(fā)現(xiàn)元素之前有 4 個(gè)元素,我們將下標(biāo) 10 的元素賦值為 10,數(shù)組是按照從前往后順序賦值的。
- 刪除
刪除數(shù)組可以使用 unset,unset ARG1[num]
可以刪除對應(yīng)下標(biāo)的數(shù)組元素,如果不帶下標(biāo)則刪除數(shù)組的全部元素,例如:
[root@master scripts]# echo ${ARG1[@]}
100 3 hello Shell 10
[root@master scripts]# unset ARG1[0] //刪除下標(biāo)為0的元素
[root@master scripts]# echo ${ARG1[@]}
3 hello Shell 10
[root@master scripts]# unset ARG1 //刪除整個(gè)數(shù)組元素
[root@master scripts]# echo ${ARG1[@]}
2.2.5 數(shù)組的切片
和其他語言一樣,可以對數(shù)組進(jìn)行切片也稱截取操作??梢酝ㄟ^ ${AEG1[@或*]:起始位置:長度}
對原數(shù)組進(jìn)行切片,返回的為字符串,例如:
[root@master scripts]# echo ${ARG1[@]}
1 2 3 hello Shell
[root@master scripts]# echo ${ARG1[@]:0:2} //從第1個(gè)元素往后2個(gè)元素進(jìn)行切片
1 2
2.2.6 數(shù)組的替換
可以替換數(shù)組中的某一個(gè)元素,例如我們將 ARG1
數(shù)組中的第 1 個(gè)元素替換為 110。
[root@master scripts]# echo ${ARG1[@]}
1 2 3 hello Shell
[root@master scripts]# echo ${ARG1[@]/1/110}
110 2 3 hello Shell
3. Shell 數(shù)組分類
我們知道了 Shell 中數(shù)組的基本操作,來看一下數(shù)組的分類。
3.1 普通數(shù)組
普通數(shù)組就是我們上面以數(shù)字為下標(biāo)的數(shù)組,上述的例子都為普通數(shù)組。
3.2 關(guān)聯(lián)數(shù)組
關(guān)聯(lián)數(shù)組是可以用字符串當(dāng)作數(shù)組下標(biāo)的一類數(shù)組,在使用關(guān)聯(lián)數(shù)組前,必須先使用 declare -A
聲明它,例如:
[root@master ~]# declare -A ARGFILE //定義管理數(shù)組
[root@master ~]# ARGFILE=([name1]=Shell [name2]=linux [name3]=arg) //關(guān)聯(lián)數(shù)組元素賦值
[root@master ~]# echo ${ARGFILE[@]} //查看所有元素
arg linux Shell
[root@master ~]# echo ${ARGFILE[name1]} //查看索引為name1的元素值
Shell
當(dāng)然也可以對單個(gè)元素進(jìn)行賦值操作, 我們可以看到關(guān)聯(lián)數(shù)組就沒有排序了,類似于其他語言中的字典,key 值也是字符串形式。
[root@master ~]# declare -A ARGLIST
[root@master ~]# ARGLIST[n1]=1
[root@master ~]# ARGLIST[n2]=2
[root@master ~]# ARGLIST[n3]="hello Shell"
[root@master ~]# echo ${ARGLIST[@]} //獲取關(guān)聯(lián)數(shù)組的所有值
2 hello Shell 1
[root@master ~]# echo ${#ARGLIST[@]} //獲取關(guān)聯(lián)數(shù)組的元素個(gè)數(shù)
3
[root@master ~]# echo ${!ARGLIST[@]} //獲取關(guān)聯(lián)數(shù)組的下標(biāo)
n2 n3 n1
4. 實(shí)例
4.1 需求
我們想利用數(shù)組統(tǒng)計(jì) linux 服務(wù)器的每 5 分鐘的網(wǎng)絡(luò)鏈接情況,查看處于各個(gè)時(shí)間段的服務(wù)器 TCP 鏈接的情況。
4.2 思路
可以利用 netstat -ant
命令來查看網(wǎng)絡(luò)鏈接情況,但是輸出的內(nèi)容我們只關(guān)心最后一列的狀態(tài),因此我們可以利用 awk 來打印從第二行開始到最后一列狀態(tài),由于 awk 命令在后續(xù)我們會(huì)詳解,在此僅作為工具使用,例如:
[root@master ~]# netstat -ant|awk 'NR>2 {print $NF}'
LISTEN
LISTEN
ESTABLISHED
TIME_WAIT
打印出來的就是最后一列的狀態(tài),我們將其內(nèi)容作為數(shù)組的下標(biāo),值為其出現(xiàn)的次數(shù),這樣就可以統(tǒng)計(jì) TCP 鏈接到狀態(tài),配合定時(shí)任務(wù)來定時(shí)統(tǒng)計(jì)服務(wù)器的 tcp 鏈接狀態(tài)。
4.3 實(shí)現(xiàn)
[root@master Shell_args]# cat tcp_status.sh
#!/bin/bash
# Description: check tcp status
# Auth: kaliarch
# Email: kaliarch@163.com
# function: net check
# Date: 2020-03-14 14:00
# Version: 1.0
# 日志目錄
LOG_FILE="/tmp/tcp_status.log"
# 定義管理數(shù)組
declare -A TCP_STATUS
# 對數(shù)組進(jìn)行內(nèi)容賦值
# 利用netstat命令來過濾出關(guān)系的一列數(shù)據(jù)
for status in $(netstat -ant|awk 'NR>2 {print $NF}')
do
# 對狀態(tài)相同狀態(tài)的TCP進(jìn)行數(shù)值累加
let TCP_STATUS[${status}]++
done
# 將統(tǒng)計(jì)完成的TCP鏈接狀態(tài)及數(shù)據(jù)記錄到日志中
for i in ${!TCP_STATUS[@]}
do
echo "$(date +%F" "%H:%m) 服務(wù)器的TCP狀態(tài)為: ${i} 的數(shù)量為: ${TCP_STATUS[${i}]}" >> ${LOG_FILE}
done
# 測試
[root@master ~]# bash tcp_status.sh
[root@master ~]# cat /tmp/tcp_status.log
2020-03-14 15:03 服務(wù)器的TCP狀態(tài)為: TIME_WAIT 的數(shù)量為: 138
2020-03-14 15:03 服務(wù)器的TCP狀態(tài)為: ESTABLISHED 的數(shù)量為: 501
2020-03-14 15:03 服務(wù)器的TCP狀態(tài)為: LISTEN 的數(shù)量為: 59
查看我們單獨(dú)運(yùn)行腳本已經(jīng)成功,可以將這個(gè)腳本加入 crontab 中,來定時(shí)執(zhí)行,后期就可以通過日志來查看當(dāng)時(shí)服務(wù)器的狀態(tài)了。
5. 注意事項(xiàng)
- 需要在實(shí)戰(zhàn)中理解數(shù)組的具體用途,尤其注意關(guān)聯(lián)數(shù)組的靈活運(yùn)用;
- 需要理解數(shù)組的全部元素,元素下標(biāo)以及元素的切片和替換,具體場景配合使用;
- 數(shù)組一般用來統(tǒng)計(jì)批量的內(nèi)容,例如批量文件的計(jì)算等,配合其他命令使用。
6. 小結(jié)
數(shù)組可謂為我們在 Shell 編程中提供了集合類型數(shù)據(jù)存儲(chǔ)的方案,對于批量數(shù)據(jù)的操作,數(shù)組功不可沒。在具體的實(shí)踐中根據(jù)數(shù)據(jù)特征,明確需求是利用數(shù)字作為下標(biāo)的數(shù)組,還是使用關(guān)聯(lián)數(shù)組,最后在實(shí)踐中靈活運(yùn)用數(shù)組的整體長度,切片,替換等操作,配合其他命令實(shí)現(xiàn)具體業(yè)務(wù)需求。