ファイル内の各項目の最大値と最小値を見つける必要があります。
#subset of my file
NEUTRON 20.900103
PION- 0.215176
PION- 22.716532
NEUTRON 8.043279
PION+ 1.374297
PION- 0.313350
PION+ 0.167848
アイテム名が複数ある場合は、ファイルを繰り返して各名前の最小値と最大値を見つける方法は?私はawkを使って各項目の数を数えましたが、重複した項目はありませんが、各名前の各繰り返しには数字が含まれています。 ex フルファイルの出力:
Name Count Minimum Maximum
-------- ----- --------- ---------
KAON- 1 5.489958 5.489958
NEUTRON 2 8.043279 20.900103
PHOTON 10 0.034664 1.897264
PION- 5 0.192247 22.716532
PION+ 7 0.167848 7.631051
PROTON 1 1.160216 1.160216
答え1
awk '{
count[$1]++
min[$1]=(!($1 in min) || $2<min[$1]) ? $2 : min[$1]
max[$1]=(!($1 in max) || $2>max[$1]) ? $2 : max[$1]
}
END {
print "Name","Count","Minimum","Maximum"
print "----","-----","-------","-------"
for(i in count) print i,count[i],min[i],max[i]
}' file | column -t
最小配列値割り当てのロジックは次のとおりです。
最初のフィールドの名前が配列に存在しない場合(!($1 in min)
)または(||
)2番目のフィールドが現在の配列値($2<min[$1]
)より小さい場合(?
)は新しい値を割り当て、$2
else(:
)は古い値を指定しますmin[$1]
。
| column -t
結果を表としてきれいに印刷するために使用されます。不要な場合は削除してください。
出力:
Name Count Minimum Maximum
---- ----- ------- -------
PION+ 2 0.167848 1.374297
PION- 3 0.215176 22.716532
NEUTRON 2 8.043279 20.900103
答え2
Jeff Schallerが指摘したように、bashはテキストプロセッサではありませんが、要求されたものは実装するのが特に難しくありません。だからここにそれをする方法があります。それだけの価値があることです。
$ awk '!/^#.*/ {
((++cnt[$1]));
if (cnt[$1]==1)
{min[$1]=max[$1]=$2}
else if ($2 < min[$1])
{ min[$1]=$2}
else if ($2 > max[$1])
{max[$1]=$2}
}
END {
printf "%-10s%7s%10s%12s\n","Name","Count","Minimum", "Maximum";
for (i in cnt)
printf "%-10s%7d%10.6g%12.8g\n", i,cnt[i],min[i],max[i];
}' testdata
出力:
Name Count Minimum Maximum
PION+ 2 0.167848 1.374297
PION- 3 0.215176 22.716532
NEUTRON 2 8.04328 20.900103
説明する:
- 次に始まる行(レコード)をスキップします。
#
awk
各レコードに対して、cnt [$ 1]はプログラム実行の開始時に0から始まり1ずつ増加します。- 現在のレコードの最初のフィールド値「$1」が以前に見たことがない場合は、その値の最小値と最大値を「$2」値に初期化します。
- 他の場合(以前のレコードに「$ 1」の値が複数回表示される場合)、最小値と最大値を更新します。
- 最後に、OPの出力例を尊重するために、フォーマットされた印刷を使用します。