我的csv文件中的第二列有重複項。我想根據這些重複添加第1列的相關值。Bash - 根據列在行中添加值
例CSV:
56, cc=DK
49, cc=US
34, cc=GB
32, cc=DE
32, cc=NZ
31, cc=DK
31, cc=GB
31, cc=GB
結果舉例:
96, cc=GB # where 96 = 34+31+31
87, cc=DK # where 87 = 56+31
32, cc=DE
32, cc=NZ
我的csv文件中的第二列有重複項。我想根據這些重複添加第1列的相關值。Bash - 根據列在行中添加值
例CSV:
56, cc=DK
49, cc=US
34, cc=GB
32, cc=DE
32, cc=NZ
31, cc=DK
31, cc=GB
31, cc=GB
結果舉例:
96, cc=GB # where 96 = 34+31+31
87, cc=DK # where 87 = 56+31
32, cc=DE
32, cc=NZ
可以在awk
使用關聯數組:
awk '{s[$2]+=$1}END{for(k in s)print s[k]", ",k}' inFile
拓展上,對於可讀性,使用sum/key
,而不是s/k
:
{ # Do for each line.
sum[$2] += $1 # Add first field to accumulator,
# indexed by second field.
# initial value is zero.
}
END { # Do this bit when whole file processed.
for (key in sum) # For each key like cc=US:
print sum[key] ", " key # Output the sum and key.
}
這裏有我的盒子樣品運行:
pax$ echo;echo '56, cc=DK
49, cc=US
34, cc=GB
32, cc=DE
32, cc=NZ
31, cc=DK
31, cc=GB
31, cc=GB' | awk '{s[$2]+=$1}END{for(k in s)print s[k]", "k}'
32, cc=DE
96, cc=GB
32, cc=NZ
49, cc=US
87, cc=DK
這工作儘管第一列的形式999,
的(注意最後的逗號),只是因爲awk
,當在數字上下文中計算字符串,只使用在該上下文中有效的前綴。因此45xyzzy
將變成45
,更重要的是,49,
變成49
。
你也可以改變FS而不是gsub(這是沒有意義的,因爲你正在改變'',並且可以使用sub,因爲它是$ 1,因爲它默認爲$ 0)根據我的代碼對這個問題的評論。 – 2015-04-01 08:13:02
@JID,我確實想到了,但事實證明gsub/sub甚至不需要,所以我刪除了它。 – paxdiablo 2015-04-01 08:26:23
哦,是的,你可以削減2個字符,因爲不需要'(k in s)'之後的'{}'。 – 2015-04-01 08:27:45
Perl的溶液:
perl -ane '$h{ $F[1] } += $F[0] }{ print "$h{$_}\t$_\n" for keys %h' input.csv
說明:
-n
處理由線-a
輸入線按空白進行分割輸入線到@F陣列}{
(稱爲「愛斯基摩人的問候語」)分開什麼是從每行代碼(-n
)執行整個輸入被處理這是確定使用awk
這種簡單的任務後運行,但如果你有很多類似的任務,你可能需要在將來改變它,很容易搞砸了。
由於這是典型的數據庫問題,請考慮使用sqlite
。
您可以:
添加行名稱和刪除多餘的空格:
$ cat <(echo "num, name") originalInput.txt | tr -d ' ' > input.csv
導入數據到臨時的SQLite數據庫:從數據庫
$ sqlite3 --batch temp.db <<EOF!
.mode csv
.import input.csv input
EOF!
選擇:
$sqlite3 temp.db 'SELECT sum(num), name FROM input GROUP BY name'
32|cc=DE
87|cc=DK
96|cc=GB
32|cc=NZ
49|cc=US
它稍微多一點的代碼,並使用外部sqlite3
命令,但它是顯著不容易出錯多靈活。你可以很容易地加入幾個CSV文件,使用奇特的排序,等等。
此外,假設你自己在六個月後查看代碼,試圖快速瞭解它的功能。
您的最後一條陳述取決於您對該語言的熟悉程度,需要更長的時間才能確定您的代碼與上面的awk相比有多長。這只是看起來像是過度殺傷。不但你必須安裝一個外部程序(每個人都可能因爲某種原因無法完成)你還必須編輯原始數據,創建一個數據庫,然後得到輸出不再以CSV格式。如果你想要比awk更強大的方法,你可以使用一個csv解析器。 – 2015-04-01 09:32:23
@JID,「可以使用awk,在這裏,但*如果你有一堆類似的任務,請考慮* sqlite」。我在製作中看到過數百個這樣的awk/sed/perl/* sh腳本,並且在很多情況下,它並不適合這項工作。順便說一句,csv解析器不會爲你做聚合。 – 2015-04-01 10:38:43
我也見過很多'魔術awk/sed/perl/* sh腳本',如果它們沒有被寫得很糟糕,並且你對這門語言有一個基本的理解,那麼你就不會立即理解正在做什麼。另外我的意思是在python或perl中使用csv解析器,閱讀它可能應該已經更清楚了。 – 2015-04-01 11:06:12
'awk -F,'{a [$ 2] + = $ 1} END {for(i in a)print a [i] FS i}'file'。你也離開了美國的輸出 – 2015-04-01 08:02:40