次のようなファイルがあります:
1
2 4 5 6 7 19
20
22
24 26 27
29 30 31 32 34 40 50 56 58
234 235 270 500
1234 1235 1236 1237
2300
実際のデータ ファイルは巨大です。そのため、このデータ ファイルの最大数を確認したいと思います。また、行内に存在する列の平均数も確認したいと思います。この小さな例では、列の最大数は 9 (5 行目) で、行内の列の平均数は 3.33 です。何か提案はありますか?
答え1
$ awk 'NF > m { m = NF } { s += NF } END { printf("Max = %d\nAvg = %g\n", m, s/NR) }' data.in
Max = 9
Avg = 3.33333
スクリプトは、 のフィールド (列) の最大数と のフィールド数の合計awk
を追跡します。入力ストリームの最後に到達すると、収集された統計情報を出力します。m
s
現在のレコード (行) のフィールド数は でNF
、これまでに読み取られたレコード数は ですNR
。
次のバージョンでも、フィールド数が最も多いレコードを追跡します。
awk 'NF > m { m = NF; r = NR } { s += NF } END { printf("Max = %d (%d)\nAvg = %g\n", m, r, s/NR) }' data.in
Max = 9 (6)
Avg = 3.33333
答え2
数学的な作業には「dc」ユーティリティを使用できます。
dc -e "
[zsmlksn]sb
[lk1+skzls+ss]sa
[[Max = ]nlmn[(]nlnn[)]n10an[Avg = ]n5klslk/1/n10an]sp
[lpxq]sq
[?z0=qlaxzlm<bcl?x]s?
0ddddsksmsnssd=?
"
上記の動作に向けて以下に示されている
tr '\t-' ' _' data.in | # dc wants negative numbers to begin with underscores
dc -e "
[
z sm # store current num of cols in register "m"
lk sn # store row num in register "n"
]sb
[
lk 1 + sk # increment the number of rows
z ls + ss # add num of cols to running sum of cols
]sa
[
[Max=]n
lmn # put max number of cols on ToS & print it
[(]n
lnn # put row num at which max number of cols are present on ToS & print it
[)]n
10an
[Avg=]n
5k ls lk /1/n # accuracy of 5 digits, compute average = sum of cols / total num of cols
10an
]sp
[
lpx # print the results by invoking the macro "p"
q # quit
]sq
# while loop for reading in lines
[
? z 0 =q # quit when no columns found in the current line read in
lax # macro "a" does: rows++, sum+=cols
z lm <b # update max cols value stored in register "lm" when cols > lm
c # clear out the line and read in the next line
l?x # read the next line
]s?
# initializations+set the ball rolling:
# register "sk" -> line kount
# register "sm" -> max cols
# register "sn" -> row number corresp. to max cols
# register "ss" -> sum of cols
0
d d d d
sk sm sn ss
d=?
"
結果
Max = 9(6)
Avg = 3.33333