日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

Bash技巧:詳解鍵值對(duì)關(guān)聯(lián)數(shù)組、一維索引數(shù)組的用法

 行者花雕 2020-02-16

Bash 的關(guān)聯(lián)數(shù)組詳解

Bash 支持關(guān)聯(lián)數(shù)組(associative arrays),可以使用任意的字符串、或者整數(shù)作為下標(biāo)來訪問數(shù)組元素。
關(guān)聯(lián)數(shù)組的下標(biāo)和值稱為鍵值對(duì),它們是一一對(duì)應(yīng)關(guān)系,鍵是唯一的,值可以不唯一。

要使用關(guān)聯(lián)數(shù)組之前,需要用 declare -A array_name 來進(jìn)行顯式聲明 array_name 變量為關(guān)聯(lián)數(shù)組。

查看 help declare 對(duì) -A 選項(xiàng)的說明如下:

-A
to make NAMEs associative arrays (if supported)

例如下面的語句定義了一個(gè)名為 filetypes 的關(guān)聯(lián)數(shù)組,并為數(shù)組賦值:

$ declare -A filetypes=([txt]=text [sh]=shell [mk]=makefile)
$ filetypes[c]="c source file"

在使用數(shù)組名進(jìn)行賦值時(shí),需要用小括號(hào) () 把所有的值括起來。

在關(guān)聯(lián)數(shù)組里面,用方括號(hào) [] 括起來的值是 key。
為方括號(hào) [] 賦予的值是該 key 對(duì)應(yīng)的 value。
不同的鍵值對(duì)之間用空格隔開。注意不是用逗號(hào)隔開。

也可以使用 filetypes[key]=value 的方式單獨(dú)為指定的關(guān)聯(lián)數(shù)組元素賦值。
如果所給的 key 之前不存在,bash 會(huì)自動(dòng)創(chuàng)建它。
如果已經(jīng)存在,則修改它的值為 value 對(duì)應(yīng)的值。

基于前面定義的 filetypes 這個(gè)數(shù)組名:

  • ${!filetypes[*]}:獲取關(guān)聯(lián)數(shù)組的所有鍵名,注意在 filetypes 前面有一個(gè)感嘆號(hào) ‘!’。

    $ echo ${!filetypes[*]}
    txt sh c mk
  • ${!filetypes[@]}: 獲取關(guān)聯(lián)數(shù)組的所有鍵名。后面會(huì)說明使用 *@ 的區(qū)別。

    $ echo ${!filetypes[@]}
    txt sh c mk
  • ${filetypes[*]}:獲取關(guān)聯(lián)數(shù)組的所有值。相比于獲取鍵名的表達(dá)式,少了前面的感嘆號(hào) ‘!’。

    $ echo ${filetypes[*]}
    text shell c source file makefile
  • ${filetypes[@]}:獲取關(guān)聯(lián)數(shù)組的所有值。

    $ echo ${filetypes[@]}
    text shell c source file makefile
  • ${#filetypes[*]}:獲取關(guān)聯(lián)數(shù)組的長度,即元素個(gè)數(shù)。注意在 filetypes 前面有一個(gè)井號(hào) ‘#’。

    $ echo ${#filetypes[*]}
    4
  • ${#filetypes[@]}:獲取關(guān)聯(lián)數(shù)組的長度,即元素個(gè)數(shù)

    $ echo ${#filetypes[@]}
    4
  • ${filetypes[key]}:獲取 key 這個(gè)鍵名對(duì)應(yīng)的值。注意大括號(hào) {} 是必須的。

    $ echo ${filetypes[sh]}
    shell
    $ echo $filetypes[sh]
    [sh]        # 可以看到,不加大括號(hào)時(shí),并不能獲取到數(shù)組元素的值

查看 man bash 的 Arrays 小節(jié),說明了這幾個(gè)表達(dá)式的含義,同時(shí)還提到使用 *@ 的區(qū)別,貼出具體的區(qū)別如下:

If the word is double-quoted, ${name[*]} expands to a single word with the value of each array member separated by the first character of the IFS special variable, and ${name[@]} expands each element of name to a separate word. When there are no array members, ${name[@]} expands to nothing.

${!name[@]} and ${!name[*]} expand to the indices assigned in array variable name. The treatment when in double quotes is similar to the expansion of the special parameters @ and * within double quotes.

即,使用 * 時(shí),如果用雙引號(hào)把整個(gè)表達(dá)式括起來,例如寫為 "${!name[*]}"、或者 "${name[*]}",那么會(huì)把所有值合并成一個(gè)字符串。

使用 @ 時(shí),如果用雙引號(hào)把整個(gè)表達(dá)式括起來,例如寫為 "${!name[@]}"、或者 "${name[@]}",那么會(huì)得到一個(gè)字符串?dāng)?shù)組。
每個(gè)數(shù)組元素會(huì)用雙引號(hào)括起來,所以數(shù)組元素自身的空格不會(huì)導(dǎo)致拆分成幾個(gè)單詞。

具體如下面的例子所示,這也是遍歷數(shù)組元素的例子:

$ for key in "${filetypes[*]}"; do echo "****:" $key; done
****: text shell c source file makefile
$ for key in "${filetypes[@]}"; do echo "@@@@:" $key; done
@@@@: text
@@@@: shell
@@@@: c source file
@@@@: makefile

可以看到,"${filetypes[*]}" 只產(chǎn)生一個(gè)字符串,for 循環(huán)只遍歷一次。
"${filetypes[@]}" 產(chǎn)生了多個(gè)字符串,for 循環(huán)遍歷多次,是一個(gè)字符串?dāng)?shù)組。
而且所給的 "c source file" 這個(gè)字符串沒有被空格隔開成幾個(gè)單詞。

上面的例子也演示了如何用 for 命令來遍歷數(shù)組元素。

可以使用 declare -p 命令來查看數(shù)組具體的鍵值對(duì)關(guān)系:

$ declare -p filetypes
declare -A filetypes='([txt]="text" [sh]="shell" [c]="c source file" [mk]="makefile" )'

Bash 的一維數(shù)組詳解

Bash 只支持一維數(shù)組 (one-dimensional indexed array),不支持二維數(shù)組。
聲明一維數(shù)組的方式是:declare -a array_name
由于 bash 不要求明確指定變量的類型,其實(shí)不聲明也可以,按數(shù)組的方式直接賦值給變量即可。

查看 help declare 對(duì) -a 選項(xiàng)的說明如下:

-a
to make NAMEs indexed arrays (if supported)

使用 declare -a 聲明的數(shù)組,默認(rèn)以數(shù)字作為數(shù)組下標(biāo),而且不需要指定數(shù)組長度。
其賦值方式說明如下:

  • array=(value1 value2 value3 ... valueN):這種方式從數(shù)組下標(biāo) 0 開始為數(shù)組元素賦值,不同值之間用空格隔開,所給的值可以是數(shù)字、字符串等。

    $ declare -a array=(1 2 "30" "40" 5)
    $ echo ${array[@]}
    1 2 30 40 5
  • array=([0]=var1 [1]=var2 [2]=var3 ... [n]=varN):這種方式顯式提供數(shù)組下標(biāo),指定為該元素賦值,所給的數(shù)組下標(biāo)可以不連續(xù)。

    $ declare -a array=([0]=1 [1]=2 [3]="30" [6]="60" [9]=9)
    $ echo ${array[@]}    # 用 ${array[@]} 獲取所有數(shù)組元素的值
    1 2 30 60 9
    $ echo ${array[5]}    # 上面賦值的時(shí)候,跳過了數(shù)組下標(biāo) 5,所以它對(duì)應(yīng)的值為空
    
    $ declare -p array    # 使用 declare -p 命令查看,會(huì)打印出被賦值的所有元素
    declare -a array='([0]="1" [1]="2" [3]="30" [6]="60" [9]="9")'
  • array[0]=value1; array[1]=value2; ...; array[n]=varN:這種方式是單獨(dú)為數(shù)組元素賦值。

    $ unset array; declare -a array
    $ array[0]=0; array[1]=1; array[7]="70"
    $ declare -p array
    declare -a array='([0]="0" [1]="1" [7]="70")'

一維數(shù)組的其他用法和前面文章介紹的關(guān)聯(lián)數(shù)組用法一樣。
例如,可以用 ${array[@]} 獲取所有數(shù)組元素的值,用 ${#array[@]} 獲取數(shù)組的元素個(gè)數(shù),等等。

可以參考下面的代碼片段來遍歷一維數(shù)組元素:

for item in "${array[@]}"; do
    echo $item
done

一維數(shù)組通過正整數(shù)來索引數(shù)組元素。
如果提供負(fù)整數(shù)的下標(biāo)值,那么它具有特殊含義,表示從數(shù)組末尾開始往前索引。
例如,array[-1] 會(huì)索引到數(shù)組的最后一個(gè)元素,array[-2] 索引到數(shù)組的倒數(shù)第二個(gè)元素,依此類推。

具體舉例說明如下:

$ declare -a array=([0]=0 [1]=1 [2]="20" [3]=3)
$ echo ${array[-1]}, ${array[-3]}
3, 1

注意:雖然 declare -a 聲明的數(shù)組要用數(shù)字作為數(shù)組下標(biāo),但是使用字符串作為數(shù)組下標(biāo)并不會(huì)報(bào)錯(cuò)。
實(shí)際測(cè)試有一些比較古怪的地方。具體舉例如下:

$ declare -a array=([0]=0 [1]=1 [2]="20" [3]=3)
$ array[index]=1000
$ echo ${array[index]}
1000
$ array[new]=2000
$ echo ${array[index]}
2000
$ echo ${array[new]}
2000
$ declare -p array
declare -a array='([0]="2000" [1]="1" [2]="20" [3]="3")'

可以看到,為 array[index] 元素賦值,沒有報(bào)錯(cuò),使用 ${array[index]} 可以正常獲取到它的值。
但是為 array[new] 賦值為 2000 后,使用 ${array[index]} 打印 index 這個(gè)字符串下標(biāo)對(duì)應(yīng)的數(shù)組元素值,發(fā)現(xiàn)變成了 2000,跟 ${array[new]} 打印的值一樣。
看起來,就像是這兩個(gè)字符串下標(biāo)關(guān)連到同一個(gè)數(shù)組元素。

實(shí)際上,它們都對(duì)應(yīng)到數(shù)組元素 0。可以看到,上面的 declare -p array 命令打印出 [0] 這個(gè)元素值變成了 2000。

查看 man bash 的 Arrays 部分,說明如下:

Indexed arrays are referenced using integers (including arithmetic expressions) and are zero-based;

An indexed array is created automatically if any variable is assigned to using the syntax name[subscript]=value.
The subscript is treated as an arithmetic expression that must evaluate to a number.

Referencing an array variable without a subscript is equivalent to referencing the array with a subscript of 0.

即,indexed array 的下標(biāo)一定是數(shù)字、或者是經(jīng)過算術(shù)表達(dá)式 (arithmetic expressions) 計(jì)算得到的數(shù)字。
如果沒有提供數(shù)組下標(biāo),默認(rèn)會(huì)使用數(shù)組下標(biāo) 0。

由于 bash 的算術(shù)表達(dá)式在獲取變量值時(shí),不需要使用 $ 符號(hào),所以上面的 array[index] 實(shí)際上相當(dāng)于 array[$index],也就是獲取 index 變量的值來作為數(shù)組下標(biāo)。

如果所給的 index 變量沒有值,就相當(dāng)于沒有提供數(shù)組下標(biāo),默認(rèn)使用數(shù)組下標(biāo) 0,所以為 array[index] 賦值,實(shí)際上是為 array[0] 賦值。
同理,為 array[new] 賦值,也是為 array[0] 賦值,會(huì)看到 array[index] 的值也跟著改變。

如果 index 變量的值不是 0,而且 new 變量沒有值,那么為 array[index] 賦值,將不會(huì)影響到 array[new]。

在上面例子的基礎(chǔ)上,繼續(xù)執(zhí)行下面語句:

$ index=1
$ array[index]=100
$ echo "array[index] = ${array[index]}, array[1] = ${array[1]}"
array[index] = 100, array[1] = 100
$ array[new]=900
$ echo "array[new] = ${array[new]}, array[0] = ${array[0]}, array[index]=${array[index]}"
array[new] = 900, array[0] = 900, array[index]=100
$ recurse=index
$ array[recurse]=500
$ echo "array[index] = ${array[index]}, array[recurse] = ${array[recurse]}, array[1] = ${array[1]}"
array[index] = 500, array[recurse] = 500, array[1] = 500

可以看到,將 index 變量賦值為 1,修改 array[index] 的值,則改變的是數(shù)組下標(biāo) 1 對(duì)應(yīng)的元素、也就是 array[1] 的值。
即相當(dāng)于用 $index 獲取該變量的值來作為數(shù)組下標(biāo)。
此時(shí),由于沒有為 new 變量賦值,修改 array[new] 的值還是關(guān)連到 array[0],不會(huì)影響到 array[index]

如果將變量賦值為字符串,那么會(huì)往下遞歸獲取該字符串對(duì)應(yīng)的變量值。
上面將 recurse 賦值為 "index" 字符串,修改 array[recurse] 的值,可以看到 array[1] 的值被改變了。
即相當(dāng)于先用 $recurse 獲取 recurse 變量的值是 "index",發(fā)現(xiàn)是字符串,繼續(xù)把 "index" 字符串作為變量名。
$index 來獲取 index 變量的值是 1,最終使用 1 作為數(shù)組下標(biāo)。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多