情景linux--如何解決read命令產生的硬編碼問題

情景

咱們知道,read命令能夠讀取文件內容,並把內容賦值給變量。shell

以以下的數據文件爲例。數組

$ cat data.txt
1 201623210021 wangzhiguo 25
2 201623210022 yangjiangbo 26
3 201623210023 yangzhen 24
4 201623210024 wangdong 23
5 201623210025 songdong 25

以上文件的四列分別爲序號(index)、學號(number)、姓名(name)、年齡(age)。用shell腳本讀取該文件並輸出每行的值:bash

$ 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

執行腳本,查看結果:學習

$ 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

不知你發現沒有,這樣的實現方式有着明顯的弊端:優化

  1. 列名(read index number name age)顯式地在代碼中指定,若是隻是想弄清楚數據文件的每列含義,則須要閱讀腳本;
  2. 該腳本中指明瞭每列的名稱,若是但願修改各字段的英文名稱(好比序號的英文名稱但願改成NUMBER)則須要修改腳本,且修改多處;
  3. 該腳本按必定順序讀取數據文件,所以,若是數據文件中的列順序發生了變化,則依然須要修改腳本;
  4. 若是有其餘數據文件須要按此方式讀取,則須要根據數據文件的實際狀況再重寫一個新腳本;

上述實現方式雖然看起來簡單,但基於上述的弊端,咱們還應對其進行優化。code

方案

解決的根本應該是寫儘量通用的腳本,不依賴數據文件自己的列數、列順序、列名稱(含義)等。table

能夠將數據文件的各字段名稱存於該數據文件的首行。當讀取數據文件時,首先讀取數據文件的首行,以獲取各字段名稱的列表;讀取其它行時,將首行的值與非首行的值進行一一對應便可。變量

數據文件擴展

$ 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

# 讀取文件頭行,存於一個數組中
tablehead=(`head -n 1 new_data.txt`)

# 從文件第二行開始讀取,按上述數組順序讀取各字段
tail -n +2 new_data.txt | while read ${tablehead[*]}
do
    # 遍歷數組的下標,獲取tablehead數組的對應值,以及以該值命名的變量的值
    for i in `seq 0 $((${#tablehead[@]}-1))`
    do
        temp=${tablehead[$i]}
        echo "${temp}:${!temp}"
    done
    echo ""
done

結果

$ 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

要寫出更通用的腳本,還能夠作一些判斷和處理,好比:數據文件做爲參數傳入、檢查數據文件的行數、檢查數據文件的列數,等等。

擴展知識

從腳本的改進上看,比原腳本略顯複雜,但卻更加通用了。
若是以爲閱讀腳本吃力,能夠有針對性地學習下,尤爲是如下知識點:

  • 數組的相關知識:數組長度、數組內容、數組元素等
  • 變量${abc}${!abc}的區別
相關文章
相關標籤/搜索