用 Bash 處理 CSV 資料
在日常的系統管理或資料分析工作中,CSV(Comma-Separated Values)格式因其輕便與通用性,經常成為資料交換的首選。雖然 Python 或 R 等語言在處理複雜資料時更具優勢,但在 Linux 環境下,若只需進行快速的資料過濾、轉換或匯出,使用 Bash 搭配原生工具(如 awk、sed、cut)往往能帶來更高的執行效率與更少的依賴安裝。
這篇文章將介紹如何在 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 模組(如 gawk 的 FPAT)或改用 csvkit 套件。
若安裝 csvkit(sudo apt install csvkit),可使用 csvformat 或 csvsql 安全處理:
# 使用 csvsql 進行更複雜的查詢
csvsql --query "SELECT name, salary FROM table WHERE department = 'Engineering'" employees.csv
2. 欄位間隔不一致或有多餘空白
有時 CSV 檔案的欄位間可能有多餘的空白字元,導致 awk 抓取錯誤。
1, Alice , Engineering ,85000
解決方法是在 awk 中使用 gsub 清除空白,或在使用 cut 後再透過 tr 或 sed 清理。例如:
awk -F',' 'NR>1 {
gsub(/^[ \t]+|[ \t]+$/, "", $2); # 移除 name 欄位前後空白
print $2
}' employees.csv
小結
對於輕量級的 CSV 處理任務,Bash 搭配 awk 與 cut 提供了極高的效率與靈活性,特別適合整合進自動化腳本或 CI/CD 流程中。雖然面對含引號、換行符號等複雜格式的 CSV 時需格外小心,但透過適當的工具選擇(如 gawk 或 csvkit),依然能穩健地解決問題。
建議在處理重要資料前,先使用 head 指令預覽檔案結構,並確認編碼與分隔符號的一致性,以確保腳本的穩定性。