逗號分隔值 別名 CSV 使用逗號作為分隔符分隔單詞的半結構化數據。 CSV 文件格式在數據專業人員中非常流行,因為需要處理大量 CSV 文件並對其進行處理以創建見解。本文重點介紹如何在 Linux Bash shell 腳本中解析 CSV 文件。
對於本文的大部分內容,我 awk
什麼時候 sed
用於解析 csv 而不是組合各種命令的工具。 grep
, cut
, tr
, ETC。
這個 awk
實用程序降低了管道多個命令或編寫帶有邏輯的循環以檢索數據的複雜性。相反,您可以: awk
我做這項工作。
內容
1. 準備 CSV 文件進行處理
CSV 文件可能是從數據庫、API 生成的,或者您已運行命令並將輸出轉換為 CSV 格式的分隔符。無論哪種情況,您都應該在運行邏輯之前分析數據集。
作為最佳實踐,您應該在使用數據集之前對其進行清理。清理數據集的原因空單元格值或標題格式不正確,正在處理不需要的額外列等。
我正在使用以下 CSV 數據,其中 凱格爾 用於演示目的。
Player_Id,Player_Name,DOB,Batting_Hand,Bowling_Skill,Country 1,SC Ganguly,8-Jul-72,Left_Hand,Right-arm medium, 2,BB McCullum,27-Sep-81,Right_Hand,Right-arm medium, 3,RT Ponting,19-Dec-74,Right_Hand,Right-arm medium, 4,DJ Hussey,15-Jul-77,Right_Hand,Right-arm offbreak,Australia 5,Mohammad Hafeez,17-Oct-80,,Right-arm offbreak,Pakistan 6,R Dravid,11-Jan-73,,Right-arm offbreak,India 7,W Jaffer,16-Feb-78,,Right-arm offbreak,India 8,V Kohli,5-Nov-88,,Right-arm medium,India 9,JH Kallis,16-Oct-75,,Right-arm fast-medium,South Africa 10,CL White,18-Aug-83,Right_Hand,Legbreak googly,Australia 11,MV Boucher,3-Dec-76,Right_Hand,Right-arm medium,South Africa 12,B Akhil,7-Oct-77,Right_Hand,Right-arm medium-fast,India 13,AA Noffke,30-Apr-77,Right_Hand,Right-arm fast-medium,Australia 14,P Kumar,2-Oct-86,Right_Hand,Right-arm medium,India 15,Z Khan,7-Oct-78,Right_Hand,Left-arm fast-medium,India
1.1。替換空單元格
在某些情況下,CSV 文件中的某些單元格沒有值。請參閱下面的屏幕截圖。列之間有一些空單元格。
始終用“NA”或“no value”替換,這樣就沒有空單元格。您可以使用 awk
該代碼段將空單元格替換為所需的值。在這種情況下,將空單元格替換為“無值”。
awk 'BEGIN{FS=",";OFS=","} { for(i=1;i<=NF;i++) { if($i == ""){ $i="No Value" } } print }' ~/Downloads/Player.csv > player_cleaned.csv
此代碼段的工作方式是將字段分隔符和輸出字段分隔符更改為逗號 (FS=",";OFS=","
)。利用 for loop
如果單元格結果為空,則遍歷行中的每個單元格 ($i == ""
),然後將其替換為 "No value"
($i="No value"
)。我需要將更改重定向到新文件。
推薦閱讀:
- 用示例解釋 Bash 重定向
1.2. 標題大寫
CSV 文件可能有也可能沒有標題。但是,如果您有標題,請始終將其設為大寫,以便於閱讀。你可以使用它 awk
還 sed
我將介紹兩種方法。
awk 'BEGIN{FS=",";OFS=","} { if(NR==1){ print toupper($0) } else { print } }' player.csv > player_cleaned.csv
這裡我們使用 ( 來檢查它是否是第一行。NR==1
) 並使用 toupper()
大寫的功能。您可以在一行中編寫相同的片段。
awk 'NR==1{ print toupper($0) }NR>1' player.csv > player_cleaned.csv
利用 awk
,更改應再次重定向到新文件。代替,’sed
‘ 將更改直接更改為文件。這裡 U
轉換為大寫。如果要轉換為小寫,請使用 L
.
$ sed -i -e '1 s/(.*)/U1/' player_cleaned.csv
$ cat player_cleaned.csv
1.3. 刪除尾隨逗號
CSV 文件可能包含尾隨逗號。要刪除尾隨逗號:
我故意在行尾加了一個逗號 7 到達 11 在我的數據文件中。
要刪除所有尾隨逗號,請運行以下命令 sed
命令:
$ sed -i 's/,$//' ~/Documents/player_cleaned.csv

這樣就完成了清潔部分。可能需要更多步驟,但這取決於 CSV 文件的結構和需要清理的內容。
2. 在終端中漂亮地打印 CSV 文件
如果您嘗試在終端中查看 CSV 文件,有一些選項可讓您以表格格式打印文件,使其更易於閱讀。
2.1. 列命令
第一種方法是使用 column
命令。在下面的命令中,Column 命令接受設置為逗號的分隔符和設置為製表符的分隔列的分隔符。您還可以設置自己的自定義分隔符。
$ cat player_cleaned.csv | column -s, -t $ column -s, -t player_cleaned.csv

2.2. CSV 搜索命令
csvlook 是包含在 csvkit 包中的實用程序。不需要像我們一樣設置分隔符 column
命令。
$ cat player_cleaned.csv | csvlook
$ csvlook player_cleaned.csv

2.3. Python 漂亮的表
如果你有蟒蛇 美麗的 安裝模塊後,您可以運行以下單行程序來重定向 CSV 文件並生成表格。
python -c "import sys,prettytable; print(prettytable.from_csv(sys.stdin))" < player_cleaned.csv
您還可以創建 別名 對於單行,將文件名作為參數傳遞。
$ alias ptable="python -c "import sys,prettytable; print(prettytable.from_csv(sys.stdin))""
$ ptable < player_cleaned.csv

3. 從 CSV 文件中獲取數據
3.1. 輸出行數和列數
要獲取 CSV 文件中的列數,請運行以下命令:變量在哪裡 NF
表示以逗號作為分隔符的字段數。
$ awk -F, 'END{print NF}' player_cleaned.csv
6
要獲取行數,請運行以下命令:變量在哪裡 NR
表示當前記錄(即)每一行都應該被視為一條記錄。
$ awk -F, 'END{print NR}' player_cleaned.csv
16
要跳過第一行(標題)併計算行數,請運行以下命令:
$ awk -F, 'END{print NR-1}' player_cleaned.csv
15
3.2. 打印整個 CSV 文件
這很容易。你可以使用它 cat
還 awk
打印整個 CSV 文件。
$ cat player_cleaned.csv
$ awk '{print}' player_cleaned.csv
3.3. 只輸出CSV文件的頭部
僅打印標題可以很好地概述 CSV 文件包含的數據類型。你可以使用它 head
還 awk
獲取個人頭銜的命令。
$ head -n 1 player_cleaned.csv
$ awk 'NR==1' player_cleaned.csv PLAYER_ID,PLAYER_NAME,DOB,BATTING HAND,BOWLING SKILL,COUNTRY
3.4. 排除標題行
要打印除標題行之外的所有其他行,請使用: awk
命令。 awk 變量 NR > 1
第一行被跳過。
$ awk '(NR>1)' player_cleansed.csv

您還可以使用 sed 過濾掉第一行並打印所有其他行。這個 1d
flag 刪除第一行並將所有其他行打印到標準輸出(終端)。
$ sed 1d < player_cleaned.csv

3.5. 打印特定列
您可以使用列位置打印整列。有兩種方法可以實現這一點。第一種方法是使用 奇怪的 第二種方法是使用 循環.awk 更容易獲得列。
默認情況下,awk根據分隔符分割行並返回值到 $1
, $2
, $3
等待。 awk 的默認分隔符是 空場.
請參閱下面的片段。字段分隔符 (FS=","
) 和輸出字段分隔符 (OFS=","
) 設置為逗號。 print 語句打印第 1、2 和 6 列。
awk 'BEGIN{FS=",";OFS=","} { print $1,$2,$6 }' player_cleansed.csv
您還可以將上述代碼段編寫為一行代碼。
awk 'BEGIN{FS=",";OFS=","}{print $1,$2,$6}' player_cleansed.csv

第二種方法是使用循環。
IFS="," while read -r -a fields do echo ${fields[0]},${fields[1]},${fields[5]} done < player_cleaned.csv
讓我解釋一下當我運行上面的代碼片段時到底發生了什麼。
- 將內部字段分隔符 IFS 設置為逗號。
- 使用 read 命令創建一個名為“fields”的數組並將輸入文件傳遞給
while loop
. - 對於每次迭代,它逐行讀取並將該行作為數組元素存儲在“字段”中,因此您可以使用數組中的索引位置單獨檢索特定列。
筆記: 索引值從0..N開始
3.6. 打印目標行
如果要打印滿足特定條件的行,可以使用 awk
讓我們看一些場景。
要打印與列值匹配的所有行,請運行以下命令:在這裡,我們嘗試打印與第 6 列中的值“India”匹配的所有行。
$ awk -F , '$6 == "India"' player_cleaned.csv

要打印與該值不匹配的所有行,請運行以下命令:代替 等式運算符,我在用著 不等於運算符.
$ awk -F , '$6 != "India"' player_cleaned.csv

您還可以使用邏輯 AND、邏輯 OR 運算符有條件地檢查多個列。假設您要檢查國家為“印度”且擊球手為“右手”的所有行。
這裡, $4
指向第4列, $6
它指向第 6 列。象徵 &&
用作邏輯 AND 運算符來評估兩個條件。
$ awk -F , '$4 == "Right_Hand" && $6 == "India"' player_cleaned.csv

如果要在條件檢查的結果中包含標頭,請使用以下命令:首先,使用打印第一行 NR==1
,然後使用邏輯 AND 運算符執行條件檢查並打印結果。
$ awk 'NR==1' player_cleaned.csv && awk -F , '$4 == "Right_Hand" && $6 == "India"' player_cleaned.csv
如果要打印或重定向輸出,請在子 shell 中運行整個命令。 括號.
$ (awk 'NR==1' player_cleaned.csv && awk -F , '$4 == "Right_Hand" && $6 == "India"' player_cleaned.csv) | column -t -s,

關於 Csvkit 的注意事項
到目前為止,您在本文中看到的一切都很簡單。但是,如果 CSV 文件具有復雜的結構,則使用上述方法進行解析可能會很繁瑣。有一個實用程序叫做 CSV 套件這是處理 CSV 文件的一個很棒的實用程序 bash。
csvkit 實用程序的問題在於它默認安裝在您的發行版中,因此您可能需要手動安裝它。在公司環境中,由於安裝外部軟件包的一些限制,這可能是不可能的。但是這個實用程序值得一提,所以我們將單獨寫一篇關於它的深入文章。
結論是
本指南展示瞭如何使用 awk、sed 處理 CSV 文件。您可以使用其他實用程序,例如 cut、grep 和 tr 來獲得您想要的結果,但是使用 awk 和 sed 可以讓生活更輕鬆,並降低編寫大量代碼的複雜性。如果您有任何反饋,請寫在評論部分。請告訴我們。
類似於閱讀:
- Bash 腳本 – 使用 getopts 解析 Bash 腳本參數
- 如何使用 Linux 命令行工具解析和打印 JSON
awkBASHBash 腳本Bash 技巧Bash 教程CLI逗號分隔值命令行CSV Shell 腳本學習CSV 文件解析Shell 腳本Shell 腳本