入力文字列に基づいて部門の平均給与を計算します。

入力文字列に基づいて部門の平均給与を計算します。

ユーザーが文字列形式で従業員の詳細を入力し、部門の平均給与を出力に表示する場合は、出力は入力文字列に表示される順序と同じでなければなりません。

たとえば、入力文字列は次のようになります。

EMP101:Jack:HR:6000#EMP102:Jill:Management:10000#EMP103:Russell:Testing:10000#EMP104:Monica:HR:15000#EMP105:John:Management:25000#EMP106:Ram:Testing:8000#EMP107:Tan:HR:15000#EMP108:Harry:Management:10000

出力文字列:

HR:12000#Management:15000#Testing:9000

次のコードを試しました。

echo "EMP101:Jack:HR:6000#EMP102:Jill:Management:10000#EMP103:Russell:Testing:10000#EMP104:Monica:HR:15000#EMP105:John:Management:25000#EMP106:Ram:Testing:8000#EMP107:Tan:HR:15000#EMP108:Harry:Management:10000" \
| awk 'BEGIN{RS="#"; OFS=FS=":"} {gsub(/"\n$/,"",$5); print $3,$4}' \
| awk -F ":" '{a[$1] += $2} {b[$1] += 1} END{for (i in a) print i, a[i]/b[i]}' \
| tr " " ":" \
| tr "\n" "#";

結果の出力は次のとおりです。

:0#Testing:9000#Management:15000#HR:12000

これは私が望むものではなく、なぜ:0#文字列の先頭に追加されるのかわかりません。誰もがシェルスクリプトでこれを達成する方法を教えてもらえますか?

ベストアンサー1

anyを使用しawkて順序を維持します。

awk 'BEGIN{ RS="#"; FS=OFS=":" }
   { ($3 in dept)?"":ordrDept[++i]=$3; dept[$3]+=$4; seenDept[$3]++; }
END{ for(o=1; o<=i; o++)
         printf "%s%d%s", ordrDept[o] OFS, 
                          dept[ordrDept[o]]/seenDept[ordrDept[o]], 
                          (i==o)?ORS:RS
}' infile

出力:

HR:12000#Management:15000#Testing:9000

我々は使用したordrDept配列は、各部門の順序を見た順序で記憶します。
我々は使用したdept 各部門の総給与をまとめた配列です。
我々は使用したseenDept彼らが見た回数を記憶する配列です。

END{...}ブロックには、i訪問した既存の部門の最大数があり、ordrDept[++i]=$3最初に訪問した順序で印刷してから、ordrDept[o]各部門の平均給与を計算total/countし、(i==o)?ORS:RS区切り記号を制御します。


上記のアプローチを実装するもう1つの方法は、より意味のある変数名を使用することです(@EdMortonに感謝します)。

BEGIN {
    RS = "#"
    FS = OFS = ":"
}
!($3 in depts2sals) {
    depts[++numDepts] = $3
}
{
    depts2sals[$3] += $4
    depts2cnts[$3]++
}
END {
    for (deptNr=1; deptNr<=numDepts; deptNr++) {
        dept = depts[deptNr]
        sal = depts2sals[dept]
        cnt = depts2cnts[dept]
        avg = sal / cnt
        printf "%s%s%s", dept OFS, avg, (deptNr<numDepts ? RS : ORS)
    }
}

おすすめ記事