逗號分隔值 別名 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 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 漂亮的表
如果你有 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
該標誌刪除第一行並將所有其他行打印到標準輸出(終端)。
$ sed 1d < player_cleaned.csv

3.5.打印特定列
您可以使用列位置打印整列。有兩種方法可以實現這一點。第一種方法是使用 awk 第二種方法是 循環.awk 更容易獲得列。
默認情況下,awk 根據分隔符拆分行並將值存儲在其中。 $1
, $2
, $3
等待。 awk 的默認分隔符是 空場..
請參閱下面的片段。字段分隔符 (FS=","
) 和輸出字段分隔符 (OFS=","
) 設置為逗號。 print 語句打印第一、第二和第六列。
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 運算符有條件地檢查多個列。假設您要檢查國家為“印度”且麵團為“Right_hand”的所有行。
這裡, $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 文件結構複雜,使用上述方法解析文件可能會很繁瑣。有一個實用程序叫做 CSVKIT用於處理 CSV 文件的優秀實用程序 bash。
csvkit 實用程序的問題在於它默認安裝在您的發行版中,並且可能需要手動安裝。由於外部軟件包安裝的一些限制,這在公司環境中可能是不可能的。但是,值得一提的是這個實用程序。為此,我將創建另一篇詳細的文章。
結論是
本指南向您展示瞭如何使用 awk、sed 處理 CSV 文件。您還可以使用其他實用程序,例如 cut、grep 和 tr 來獲得您想要的結果,但是使用 awk 和 sed 可以使您的工作更輕鬆,並降低編寫大量代碼的複雜性。如果您有任何意見,請寫在評論部分。我們期待您的回音。
類似於閱讀:
- Bash Script-使用getopts解析Bash腳本參數
- 如何使用 Linux 命令行工具解析和打印 JSON
awkBASHBash ScriptingBashTipsBashTutorialCLI逗號分隔命令行 CSV LearningShellScriptingParsing CSV FilesedShell ScriptingShell Scripting