情景
我們知道,read命令可以讀取文件內(nèi)容,并把內(nèi)容賦值給變量。
以如下的數(shù)據(jù)文件為例。
$ cat data.txt
1 201623210021 wangzhiguo 25 2 201623210022 yangjiangbo 26 3 201623210023 yangzhen 24 4 201623210024 wangdong 23 5 201623210025 songdong 25
以上文件的四列分別為序號(hào)(index)、學(xué)號(hào)(number)、姓名(name)、年齡(age)。用shell腳本讀取該文件并輸出每行的值:
$ cat read_data.sh
#!/bin/bash cat data.txt | while read index number name age do echo "index:${index}" echo "number:${number}" echo "name:${name}" echo "age:${age}" echo " " done
執(zhí)行腳本,查看結(jié)果:
$ sh read_data.sh
index:1 number:201623210021 name:wangzhiguo age:25 index:2 number:201623210022 name:yangjiangbo age:26 index:3 number:201623210023 name:yangzhen age:24 index:4 number:201623210024 name:wangdong age:23 index:5 number:201623210025 name:songdong age:25
不知你發(fā)現(xiàn)沒(méi)有,這樣的實(shí)現(xiàn)方式有著明顯的弊端:
-
列名(read index number name age)顯式地在代碼中指定,如果只是想弄清楚數(shù)據(jù)文件的每列含義,則需要閱讀腳本;
-
該腳本中指明了每列的名稱,如果希望修改各字段的英文名稱(比如序號(hào)的英文名稱希望改為NUMBER)則需要修改腳本,且修改多處;
-
該腳本按一定順序讀取數(shù)據(jù)文件,因此,如果數(shù)據(jù)文件中的列順序發(fā)生了變化,則依然需要修改腳本;
-
如果有其他數(shù)據(jù)文件需要按此方式讀取,則需要根據(jù)數(shù)據(jù)文件的實(shí)際情況再重寫一個(gè)新腳本;
上述實(shí)現(xiàn)方式雖然看起來(lái)簡(jiǎn)單,但基于上述的弊端,我們還應(yīng)對(duì)其進(jìn)行優(yōu)化。
方案
解決的根本應(yīng)該是寫盡可能通用的腳本,不依賴數(shù)據(jù)文件本身的列數(shù)、列順序、列名稱(含義)等。
可以將數(shù)據(jù)文件的各字段名稱存于該數(shù)據(jù)文件的首行。當(dāng)讀取數(shù)據(jù)文件時(shí),首先讀取數(shù)據(jù)文件的首行,以獲取各字段名稱的列表;讀取其它行時(shí),將首行的值與非首行的值進(jìn)行一一對(duì)應(yīng)即可。
數(shù)據(jù)文件
$ cat new_data.txt
index number name age 1 201623210021 wangzhiguo 25 2 201623210022 yangjiangbo 26 3 201623210023 yangzhen 24 4 201623210024 wangdong 23 5 201623210025 songdong 25
腳本
$ cat new_read_data.sh
#!/bin/bash # 讀取文件頭行,存于一個(gè)數(shù)組中 tablehead=(`head -n 1 new_data.txt`) # 從文件第二行開(kāi)始讀取,按上述數(shù)組順序讀取各字段 tail -n +2 new_data.txt | while read ${tablehead[*]} do # 遍歷數(shù)組的下標(biāo),獲取tablehead數(shù)組的對(duì)應(yīng)值,以及以該值命名的變量的值 for i in `seq 0 $((${#tablehead[@]}-1))` do temp=${tablehead[$i]} echo "${temp}:${!temp}" done echo "" done
結(jié)果
$ sh new_read_data.sh
index:1 number:201623210021 name:wangzhiguo age:25 index:2 number:201623210022 name:yangjiangbo age:26 index:3 number:201623210023 name:yangzhen age:24 index:4 number:201623210024 name:wangdong age:23 index:5 number:201623210025 name:songdong age:25
要寫出更通用的腳本,還可以做一些判斷和處理,比如:數(shù)據(jù)文件作為參數(shù)傳入、檢查數(shù)據(jù)文件的行數(shù)、檢查數(shù)據(jù)文件的列數(shù),等等。
擴(kuò)展知識(shí)
從腳本的改進(jìn)上看,比原腳本略顯復(fù)雜,但卻更加通用了。
如果覺(jué)得閱讀腳本吃力,可以有針對(duì)性地學(xué)習(xí)下,尤其是以下知識(shí)點(diǎn):
-
數(shù)組的相關(guān)知識(shí):數(shù)組長(zhǎng)度、數(shù)組內(nèi)容、數(shù)組元素等
-
變量${abc}和${!abc}的區(qū)別