2016-05-30 38 views
1

我是新來這個網站,並試圖學習awk。我試圖找到field3的最大值,按field1分組並打印所有最大值的字段。字段2包含時間,這意味着對於每個ITEM1有FIELD2,字段3的96個值和field4中awk組由多個列和非主鍵打印最大值

輸入文件:(逗號隔開)

item1,00:15,10,30 
item2,00:45,20,45 
item2,12:15,30,45 
item1,00:30,20,56 
item3,23:00,40,44 
item1,12:45,50,55 
item3,11:15,30,45 

期望的輸出:

item1,12:45,50,55 
item2,12:15,30,45 
item3,11:15,30,45 

我到目前爲止已經試過:

BEGIN{ 
FS=OFS=","} 
{ 
if (a[$1]<$3){ 
    a[$1]=$3} 
} 
END{ 
for (i in a){ 
print i,a[i] 
} 

但這只是打印

item1,50 
item2,30 
item3,30 

但我需要打印相應的field2和field4的最大值,如所需的輸出中所示。請幫忙。

+0

注輸出應該是'item3,23:00,40,44',因爲40是item3最大的第3列。 – fedorqui

+0

如果可能發生,則在輸入/輸出中包含具有相同$ 1和$ 3但不同$ 2值的行,以便我們可以看到是否要輸出第一個或最後一個或所有匹配行。如果它不能發生然後說明。 –

+0

@Ed Morton對於同樣的$ 1,$ 2是不同的,$ 3可以是相同的。關於你提出的解決方案它的工作原理,我只是不明白不使用!(最大$ 1)塊的結果。另一件我剛纔想到的情況是,如果兩列中的組分別表示$ 1和$ 2,那麼這個!(最大$ 1)塊和排序是如何工作的? – foxx

回答

3

這裏的問題是,你沒有存儲整行,所以當你瀏覽最後的數據時,沒有完整的數據要打印。

你需要做的就是用另一個數組,說data[index]=full line

BEGIN{ 
FS=OFS=","} 
{ 
if (a[$1]<$3){ 
    a[$1]=$3 
    data[$1]=$0}  # store it here! 
} 
END { 
    for (i in a) 
     print data[i] # print it here 
} 

或者作爲一個班輪:

$ awk 'BEGIN{FS=OFS=","} {if (a[$1]<$3) {a[$1]=$3; data[$1]=$0}} END{for (i in a) print data[i]}' file 
item1,12:45,50,55 
item2,12:15,30,45 
item3,23:00,40,44 
2

隨着sort命令的幫助不大:

sort -t, -k1,1 -k3,3nr file | awk -F, '!seen[$1]++' 
+0

不錯的解決方案! –

+0

@EdMorton謝謝! :)讓我添加一些東西。我最近告訴過,GNU'sort -u'擴展只是有用的。這個案例就是一個很好的例子。雖然基本上存在'-u'標誌,但在大多數情況下,您需要更詳細的重複數據刪除功能。儘管很多GNU擴展對於imo都很有幫助,但至少對於交互式使用來說,可能'sort -u'不值得擴展。 – hek2mgl

+0

'-u'不是一個GNU擴展,它在第1天就存在於所有'sort's中。它實際上對'sort |非常有用uniq'。如果你可以將它與一個鍵相關聯,那將會很好,所以你可以做一些類似'sort -t,-k3,3nr -k1,1u file'的文件,然後跳過awk! –

1

要穩健地完成這項工作,您需要:

$ cat tst.awk 
BEGIN { FS="," } 
!($1 in max) { 
    max[$1] = $3 
    data[$1] = $0 
    keys[++numKeys] = $1 
} 
$3 > max[$1] { 
    max[$1] = $3 
    data[$1] = $0 
} 
END { 
    for (keyNr=1; keyNr<=numKeys; keyNr++) { 
     print data[keys[keyNr]] 
    } 
} 

$ awk -f tst.awk file 
item1,12:45,50,55 
item2,12:15,30,45 
item3,23:00,40,44 

在進行最小/最大計算時,您應該始終使用讀取的第一個值對最小/最大值進行排序,而不是假設它總是小於或大於某個任意值(例如,如果跳過上面的!($1 in max)塊,則爲零或零)。

當打印輸出時,您需要keys數組來保留輸入順序。如果您使用in,則輸出順序將是隨機的。

需要注意的是地道的awk的語法很簡單:

<condition> { <action> } 

不是C風格:

{ if (<condition>) { <action> } }