逗號分隔值 別名 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”或“無值”,以便沒有空單元格。您可以使用 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
命令。在下面的命令中,列命令接受設置為逗號的分隔符和設置為製表符的列分隔符。您還可以設置自己的自定義分隔符。
$ 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
awkBASH Bash 腳本 Bash 技巧 Bash 教程 CLI 逗號分隔值 命令行 CSV 學習 Shell 腳本 CSV 文件解析 sedShell 腳本 Shell 腳本