用 Bash 處理 CSV 資料 文章首圖

用 Bash 處理 CSV 資料

用 Bash 處理 CSV 資料

在日常的系統管理或資料分析工作中,CSV(Comma-Separated Values)格式因其輕便與通用性,經常成為資料交換的首選。雖然 Python 或 R 等語言在處理複雜資料時更具優勢,但在 Linux 環境下,若只需進行快速的資料過濾、轉換或匯出,使用 Bash 搭配原生工具(如 awksedcut)往往能帶來更高的執行效率與更少的依賴安裝。

這篇文章將介紹如何在 Ubuntu 22.04 或 Debian 12 環境中,利用 Bash 腳本高效地處理 CSV 檔案,並解決常見的格式陷阱。

基礎環境準備

首先,我們需要一個測試用的 CSV 檔案。請在終端機中建立一個名為 employees.csv 的檔案,內容如下:

id,name,department,salary
1,Alice,Engineering,85000
2,Bob,Marketing,62000
3,Charlie,Engineering,92000
4,Diana,Sales,58000
5,Eve,Marketing,65000

注意:為了避免編碼問題,請確保檔案以 UTF-8 格式儲存,且行尾使用 Unix 格式(LF),而非 Windows 格式(CRLF)。若檔案來自 Windows,可先使用 dos2unix employees.csv 進行轉換。

常用處理技巧與範例

1. 使用 awk 進行欄位提取與過濾

awk 是處理 CSV 最強大的工具之一。預設情況下,awk 以空白字元為分隔符號,但透過 -F 參數,我們可以指定逗號作為分隔符。

範例一:僅輸出特定欄位(例如:姓名與薪資)

awk -F',' 'NR>1 {print $2 ", " $4}' employees.csv
  • -F',':設定輸入分隔符號為逗號。
  • NR>1:跳過第一列的標題列(Record Number > 1)。
  • $2$4:分別代表第二欄(name)與第四欄(salary)。

範例二:條件過濾(例如:找出 Engineering 部門且薪資高於 80000 的人員)

awk -F',' 'NR>1 && $3=="Engineering" && $4>80000 {print $2, $4}' employees.csv

2. 使用 cut 進行快速欄位抽取

若只需簡單地提取單一欄位,cut 指令更為直觀且輕量。

# 提取第三欄(department)
cut -d',' -f3 employees.csv
  • -d',':指定分隔符為逗號。
  • -f3:指定輸出第三欄。

3. 完整腳本範例:自動匯出高階工程師名單

以下是一個完整的 Bash 腳本範例,示範如何整合多個工具,將符合條件的資料匯出為新檔案。

#!/bin/bash

# 設定輸入與輸出檔案
INPUT_FILE="employees.csv"
OUTPUT_FILE="senior_engineers.csv"

# 檢查輸入檔案是否存在
if [[ ! -f "$INPUT_FILE" ]]; then
    echo "錯誤:找不到檔案 $INPUT_FILE"
    exit 1
fi

# 使用 awk 處理資料
# 1. 跳過標題列 (NR>1)
# 2. 檢查部門是否為 Engineering ($3 == "Engineering")
# 3. 檢查薪資是否大於 80000 ($4 > 80000)
# 4. 輸出 id, name, salary 到新檔案
awk -F',' 'NR>1 && $3=="Engineering" && $4>80000 {
    print $1 "," $2 "," $4
}' "$INPUT_FILE" > "$OUTPUT_FILE"

# 顯示處理結果
if [[ $? -eq 0 ]]; then
    echo "處理完成!高階工程師名單已儲存至 $OUTPUT_FILE"
    echo "內容如下:"
    cat "$OUTPUT_FILE"
else
    echo "處理過程中發生錯誤。"
fi

執行此腳本後,將產生包含 Alice 與 Charlie 資訊的新檔案。

常見問題與解決方案

1. CSV 欄位中包含逗號怎麼辦?

標準 CSV 格式允許欄位值內包含逗號,但必須用雙引號 " 包裹。例如:1,"Smith, John",Sales,50000

上述的 awk -F',' 方法在遇到此情況時會錯誤分割欄位。此時建議使用專門處理 CSV 的 awk 模組(如 gawkFPAT)或改用 csvkit 套件。

若安裝 csvkitsudo apt install csvkit),可使用 csvformatcsvsql 安全處理:

# 使用 csvsql 進行更複雜的查詢
csvsql --query "SELECT name, salary FROM table WHERE department = 'Engineering'" employees.csv

2. 欄位間隔不一致或有多餘空白

有時 CSV 檔案的欄位間可能有多餘的空白字元,導致 awk 抓取錯誤。

1, Alice , Engineering ,85000

解決方法是在 awk 中使用 gsub 清除空白,或在使用 cut 後再透過 trsed 清理。例如:

awk -F',' 'NR>1 {
    gsub(/^[ \t]+|[ \t]+$/, "", $2); # 移除 name 欄位前後空白
    print $2
}' employees.csv

小結

對於輕量級的 CSV 處理任務,Bash 搭配 awkcut 提供了極高的效率與靈活性,特別適合整合進自動化腳本或 CI/CD 流程中。雖然面對含引號、換行符號等複雜格式的 CSV 時需格外小心,但透過適當的工具選擇(如 gawkcsvkit),依然能穩健地解決問題。

建議在處理重要資料前,先使用 head 指令預覽檔案結構,並確認編碼與分隔符號的一致性,以確保腳本的穩定性。