Shell script 讀取檔案並解析類 csv 格式

Shell script 讀取檔案並解析類 csv 格式

2021, Jul 23    

有時候在撰寫 shell script 時,資料來源可能是一份預先產生的檔案,可能是 log 或是一些多行的輸出,那就沒辦法用一般讀值的方式去處理,如果又涉及特殊的格式像是 csv 這樣的又該怎麼處理呢

讀取多行的資料源

說是讀取檔案,但對於 shell script 其實就是讀取多行的資料源,一般的字串輸入可以透過參數傳入,但是多行的資料通常會希望一行一行讀取,可以寫成像是:

# test.sh
count=0
while read line; do
    let count++
    echo "$count $line"
done

使用上

ls -l | test.sh

透過 while read line 的寫法可以把傳入 script 的資料來源一行一行讀入

讀取檔案

那要用到讀取檔案上也可以像上面的做法

cat "file.txt" | test.sh

也可以透過檔案名稱把指定的檔案加入到資料流當中

count=0
while read line; do
    let count++
    echo "$count $line"
done < "test.sh"

而就像我們常用的 grep 等指令都是可以讀檔案又讀 pipe 傳入資料的可以參考下面寫法

function addLineNumber(){
    let count=0
    while read line; do
        let count++
        echo "$count $line"
    done
}

for file in $@; do
    echo $file
    addLineNumber < $file
done

addLineNumber

read 在預設會去讀取 stdin 的來源內容,因此可以用來接收 pipe 的資料

解析 csv

如果今天有個檔案如下

1,test,hello world

那想要讀取個別元素時可以寫成下面,IFS 是一個特別的變數,是 read 用來分割字段的依據,所以我們可以預先設定好 IFS 的值來做到字段的切割

IFS=","
while read number title content; do
    echo "number: $number, title: $title, content: $content"
done < "test.csv"

或是直接寫在 while

while IFS="," read number title content; do
    echo "number: $number, title: $title, content: $content"
done < "test.csv"

其他

如果檔案內容不是簡單的用一個 , 去隔開,而是有複雜結構的話,可以參考用前篇所提到的字串處理,來分析複雜的資料結構