情景l(fā)inux–read命令產(chǎn)生的硬編碼問(wèn)題怎么解決?

情景

我們知道,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)方式有著明顯的弊端:

  1. 列名(read index number name age)顯式地在代碼中指定,如果只是想弄清楚數(shù)據(jù)文件的每列含義,則需要閱讀腳本;

  2. 該腳本中指明了每列的名稱,如果希望修改各字段的英文名稱(比如序號(hào)的英文名稱希望改為NUMBER)則需要修改腳本,且修改多處;

  3. 該腳本按一定順序讀取數(shù)據(jù)文件,因此,如果數(shù)據(jù)文件中的列順序發(fā)生了變化,則依然需要修改腳本;

  4. 如果有其他數(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ū)別

? 版權(quán)聲明
THE END
喜歡就支持一下吧
點(diǎn)贊10 分享