[英]Awk: How do I count occurrences of a string across columns and find the maximum across rows?
我在 Linux 上的bash
腳本有問題。
我的輸入如下所示:
input
Karydhs y n y y y n n y n n n y n y n
Markopoulos y y n n n y n y n y y n n n y
name3 y n y n n n n n y y n y n y n
等等...
其中 y=yes 和 n=no,這是投票的結果......現在我想使用awk
來顯示每個人(姓名)和獲勝者(獲得最多 y ), 有任何想法嗎?
我做這樣的事情:
awk '{count=0 for (I=1;i<=15;i++) if (a[I]="y") count++} {print $1,count}' filename
這是一個快速(不需要排序,沒有明確的“for”循環),考慮到關系可能性的一次性解決方案:
awk 'NF==0{next}
{name=$1; $1=""; gsub(/[^y]/,"",$0); l=length($0);
print name, l;
if (mx=="" || mx < l) { mx=l; tie=""; winner=name; }
else if (mx == l) {
tie = 1; winner = winner", "name;
}
}
END {fmt = tie ? "The winners have won %d votes each:\n" :
"The winner has won %d votes:\n";
printf fmt, mx;
print winner;
}'
輸出:
Karydhs 7
Markopoulos 7
name3 6
The winners have won 7 votes each:
Karydhs, Markopoulos
注意:上面的程序是為了可讀性而提供的,但可以接受 GNU awk 顯示的換行符。 某些 awk 不允許拆分三元條件。
那這個呢?
awk '{ for (i=2;i<NF;i++) { if ($i=="y") { a[$1" "$i]++} } } END { print "Yes tally"; l=0; for (i in a) { print i,a[i]; if (l>a[i]) { l=l } else { l=a[i];name=i } } split(name,a," "); print "Winner is ",a[1],"with ",l,"votes" } ' f
Yes tally
name3 y 6
Markopoulos y 6
Karydhs y 7
Winner is Karydhs with 7 votes
替代的兩遍awk
$ awk '{print $1; $1=""}1' votes |
awk -Fy 'NR%2{printf "%s ",$0; next} {print NF-1}' |
sort -k2nr
Karydhs 7
Markopoulos 7
name3 6
這是另一種方法。
{ name=$1; $1=""; votes[name]=length(gensub("[^y]","","g")); }
END {asorti(votes,rank); for (r in rank) print rank[r], votes[rank[r]]; }
它類似於@mklement0 的答案,但它使用asorti()
¹ 在 awk 內部進行排序。
name=$1
保存令牌 1 中的名稱$1="";
清除令牌 1,其副作用是將其從 $0 中刪除votes[name]
是一個以候選人姓名為索引的數組gensub("[^y]","","g")
從 $0 的剩余部分刪除除 'y 之外的所有內容length()
計算它們asorti(votes,rank)
按索引對投票進行排序; 此時數組如下所示:
votes rank [name3] = 6 [1] = Karydhs [Markopoulos] = 7 [2] = Markopoulos [Karydhs] = 7 [3] = name3
for (r in rank) print rank[r], votes[rank[r]];
打印結果:
Karydhs 7 Markopoulos 7 name3 6
¹ asorti()
函數在某些版本的 awk 中可能不可用
一個更簡單且符合 POSIX 標准的awk
解決方案,由sort
輔助; 請注意,沒有明確打印獲勝者信息(可能適用於多行),但按降序排序的投票應該使獲勝者顯而易見。
awk '{
printf "%s", $1
$1=""
yesCount=gsub("y", "")
printf " %s\n", yesCount
}' file |
sort -t ' ' -k2,2nr
printf "%s", $1
打印名稱字段,沒有尾隨換行符。$1=""
清除第一個字段,導致$0
輸入行被重建,以便它只包含投票列。yesCount=gsub("y", "")
執行一個虛擬替換,它利用了這樣一個事實,即 Awk 的gsub()
函數返回執行的替換計數; 實際上,返回值是行上y
值的數量。printf " %s\\n", yesCount
然后打印 yes 票數作為第二個輸出字段並終止該行。sort -t ' ' -k2,2,nr
然后按第二個 ( -k2,2
) 空格分隔 ( -t ' '
) 字段按數字 ( n)
以相反的順序 ( r
) 對結果行進行排序,以便最高的贊成票首先出現。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.