2015-04-01 57 views
4

我的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 
+1

'awk -F,'{a [$ 2] + = $ 1} END {for(i in a)print a [i] FS i}'file'。你也離開了美國的輸出 – 2015-04-01 08:02:40

回答

2

可以在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

+0

你也可以改變FS而不是gsub(這是沒有意義的,因爲你正在改變'',並且可以使用sub,因爲它是$ 1,因爲它默認爲$ 0)根據我的代碼對這個問題的評論。 – 2015-04-01 08:13:02

+0

@JID,我確實想到了,但事實證明gsub/sub甚至不需要,所以我刪除了它。 – paxdiablo 2015-04-01 08:26:23

+1

哦,是的,你可以削減2個字符,因爲不需要'(k in s)'之後的'{}'。 – 2015-04-01 08:27:45

1

Perl的溶液:

perl -ane '$h{ $F[1] } += $F[0] }{ print "$h{$_}\t$_\n" for keys %h' input.csv 

說明:

  • -n處理由線
  • -a輸入線按空白進行分割輸入線到@F陣列
  • 中的字段哈希表%h記錄每個鍵的總和(2 nd列)。它只是將第一列的值添加到它。
  • }{(稱爲「愛斯基摩人的問候語」)分開什麼是從每行代碼(-n)執行整個輸入被處理
0

這是確定使用awk這種簡單的任務後運行,但如果你有很多類似的任務,你可能需要在將來改變它,很容易搞砸了。

由於這是典型的數據庫問題,請考慮使用sqlite

您可以:

  1. 添加行名稱和刪除多餘的空格:

    $ cat <(echo "num, name") originalInput.txt | tr -d ' ' > input.csv 
    
  2. 導入數據到臨時的SQLite數據庫:從數據庫

    $ sqlite3 --batch temp.db <<EOF! 
    .mode csv 
    .import input.csv input 
    EOF! 
    
  3. 選擇:

    $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文件,使用奇特的排序,等等。

此外,假設你自己在六個月後查看代碼,試圖快速瞭解它的功能。

+1

您的最後一條陳述取決於您對該語言的熟悉程度,需要更長的時間才能確定您的代碼與上面的awk相比有多長。這只是看起來像是過度殺傷。不但你必須安裝一個外部程序(每個人都可能因爲某種原因無法完成)你還必須編輯原始數據,創建一個數據庫,然後得到輸出不再以CSV格式。如果你想要比awk更強大的方法,你可以使用一個csv解析器。 – 2015-04-01 09:32:23

+0

@JID,「可以使用awk,在這裏,但*如果你有一堆類似的任務,請考慮* sqlite」。我在製作中看到過數百個這樣的awk/sed/perl/* sh腳本,並且在很多情況下,它並不適合這項工作。順便說一句,csv解析器不會爲你做聚合。 – 2015-04-01 10:38:43

+1

我也見過很多'魔術awk/sed/perl/* sh腳本',如果它們沒有被寫得很糟糕,並且你對這門語言有一個基本的理解,那麼你就不會立即理解正在做什麼。另外我的意思是在python或perl中使用csv解析器,閱讀它可能應該已經更清楚了。 – 2015-04-01 11:06:12