文書:
Name: Rad
Eng: 94
Tam: 98
Mat: 98
Soc: 98
Sci: 80
Name: Din
Eng: 87
Tam: 89
Mat: 78
Soc: 87
Sci: 34
Name: Hardy
Eng: 78
Tam: 87
Mat: 23
Soc: 34
Sci: 98
スクリプト:
#!/bin/bash
file=$1
num=$2
n=`wc -l < $file`
it=$((n/num))
echo $n
echo $it
awk -v numm="$num" '{if (NR<=numm){T+=$2}}END{print T}' $file
上記のスクリプトは、最初の生徒の総数を生成できます。また、残りの二人の生徒の総点も手に入れたいです。誰かが私を助けることができますか?
答え1
awk '/^Name:/ { if (name) printf("%s, score = %d\n", name, score); name = $2; score = 0; next }
{ score += $2 }
END { printf("%s, score = %d\n", name, score) }' file
結果:
Rad, score = 468
Din, score = 375
Hardy, score = 320
awk
文字列で始まるすべての行に対して最初のブロックを実行しますName:
。変数に値がある場合、name
前の生徒の総点はその生徒の名前で印刷されます。その後、名前は現在の行の2番目のフィールドに設定され、スコアはゼロにリセットされます。その後、スクリプトはすぐに次の入力行に進みます。
第2のブロックは、前のブロックで処理されなかった入力の各行に対して実行される。score
変数値にスコアを追加するだけです。
最後のブロックはファイルの最後の行を読み取った後に実行され、最初のブロックで実行された出力をエミュレートします。最後の学生の結果を出力することです。
コードをコピーするのは面倒なので、出力を実行する関数を使用するソリューションは次のとおりです。
awk 'function output() { if (name) printf("%s, score = %d\n", name, score) }
/^Name:/ { output(); name = $2; score = 0; next }
{ score += $2 }
END { output() }' file
これは質問の一部ではありませんが、興味深いことがあります。
awk 'function output() { if (name) printf("%s\t score = %3d, mean = %.1f\n", name, score, score/count) }
/^Name:/ { output(); name = $2; score = count = 0; next }
{ score += $2; ++count }
END { output() }' file
出力:
Rad score = 468, mean = 93.6
Din score = 375, mean = 75.0
Hardy score = 320, mean = 64.0
答え2
検索できName
、1つが見つかるたびに次の行にnumm
移動してスコアを合計します。
#!/bin/bash
file=$1
num=$2
awk -v numm="$num" '
/Name/{
mark = 0;
printf("%s ",$2);
for ( i=0; i<numm ; i++){
getline;
mark += $2;
}
printf("%d\n", mark);
}' $file
結果:
Rad 468
Din 375
Hardy 320
答え3
同じ効果を得るには、次のコマンドを見つけます。
注文する:
for i in Rad Din Hardy
> do
> sed -n "/$i/,+5p" p.txt| awk -F ":" '{print $2}'| sed "/$i/d"| awk -v i="$i" 'BEGIN{sum=0}{sum=sum+$1}END {print "Total marks of " i " " sum}'
> done
出力
Total marks of Rad 468
Total marks of Din 375
Total marks of Hardy 320