以下には、3番目の列の日付に基づいて複数のファイルに分割する必要がある入力ファイルがあります。デフォルトでは、同じ日付のすべての取引は特定の日付のファイルに分割する必要があります。分割したら、タイトルと予告編を作成する必要があります。予告編の4番目の列には、レコード数と金額の合計(その日の金額の合計)を含める必要があります。このような場合、上記のように数字が非常に大きいのですが、下のコードでbcをどのように統合できますか?
入力ファイル
H|~^20200425|~^abcd|~^sum
R|~^abc|~^2019-03-06T12:33:52.27|~^123562388.23456|~^2018-04-12T12:33:52.27|~^hhh
R|~^abc|~^2019-03-05T12:33:52.27|~^105603.042|~^2018-10-23T12:33:52.27|~^aus
R|~^abc|~^2019-03-05T12:33:52.27|~^2054.026|~^2018-10-24T12:33:52.27|~^usa
R|~^abc|~^2019-03-06T12:33:52.27|~^10.00|~^2018-09-11T12:33:52.27|~^virginia
R|~^abc|~^2019-03-05T12:33:52.27|~^30.00|~^2018-08-05T12:33:52.27|~^ddd
R|~^abc|~^2019-03-06T12:33:52.27|~^15.03|~^2018-10-23T12:33:52.27|~^jjj
R|~^abc|~^2019-03-06T12:33:52.27|~^10.04|~^2018-04-08T12:33:52.27|~^jj
R|~^abc|~^2019-03-05T12:33:52.27|~^20.00|~^2018-07-23T12:33:52.27|~^audg
T|~^20200425|~^8|~^xxx|~^123670130.37256
出力ファイル 20190305.txt
H|~^20200425|~^abcd|~^sum
R|~^abc|~^2019-03-05T12:33:52.27|~^105603.042|~^2018-10-23T12:33:52.27|~^aus
R|~^abc|~^2019-03-05T12:33:52.27|~^2054.026|~^2018-10-24T12:33:52.27|~^usa
R|~^abc|~^2019-03-05T12:33:52.27|~^30.00|~^2018-08-05T12:33:52.27|~^ddd
R|~^abc|~^2019-03-05T12:33:52.27|~^20.00|~^2018-07-23T12:33:52.27|~^audg
T|~^20200425|~^4|~^xxx|~^107707.068
出力ファイル 20190306.txt
H|~^20200425|~^abcd|~^sum
R|~^abc|~^2019-03-06T12:33:52.27|~^123562388.23456|~^2018-04-12T12:33:52.27|~^hhh
R|~^abc|~^2019-03-06T12:33:52.27|~^10.00|~^2018-09-11T12:33:52.27|~^virginia
R|~^abc|~^2019-03-06T12:33:52.27|~^15.03|~^2018-10-23T12:33:52.27|~^jjj
R|~^abc|~^2019-03-06T12:33:52.27|~^10.04|~^2018-04-08T12:33:52.27|~^jj
T|~^20200425|~^4|~^xxx|~^123562423.30456
私が使用しているコード(PS:コミュニティメンバーの1人が提案する)awk
解決策は次のとおりです。
awk -F'\\|~\\^' '{
if($1=="H"){
head=$0
}
else if($1=="T"){
foot=$1"|~^"$2
foot4=$4
}
else{
date=$3;
sub("T.*","", date);
data[date][NR]=$0;
sum[date]+=$4;
num[date]++
}
}
END{
for(date in data){
file=date".txt";
gsub("-","",file);
print head > file;
for(line in data[date]){
print data[date][line] > file
}
printf "%s|~^%s|~^%s|~^%s\n", foot, num[date],
foot4, sum[date] > file
}
}' file
コードは非常にうまく動作します。しかし、この段階では
sum[date]+=$4;
大きな数を合わせることはできません。最後のステップで使用しているため、%s
トレーラーの合計は指数値で印刷されます。
printf "%s|~^%s|~^%s|~^%s\n", foot, num[date],
foot4, sum[date] > file
ここでは、大きな数字に合計を適用し、正確な合計を印刷したいと思います。 (ここでbc(bash電卓)を試しましたが、合計が配列に基づいて特定の日付に基づいて追加されるため停止しました。)この問題を解決するのに役立ちます
また、"%.15g"
トレーラーのステップを試しました。
printf "%s|~^%s|~^%s|~^%.15g\n", foot, num[date],
foot4, sum[date] > file
ここで結果が15桁(小数点を含む)であれば、正確な合計を求めることができます。合計結果が15桁を超える場合、この方法は効果がありません。助けてください
ベストアンサー1
awk
大きな数字の問題を無視して、次のプログラムを作成します。
BEGIN {
FS = "\\|~\\^"
OFS= "|~^"
}
$1 == "H" {
header = $0
}
$1 == "R" {
name = $3
sub("T.*", "", name)
sum[name] += $4
cnt[name] += 1
if (cnt[name] == 1)
print header >name ".txt"
print >name ".txt"
}
$1 == "T" {
for (name in sum)
print $1, $2, cnt[name], $4, sum[name] >name ".txt"
}
便宜上、出力フィールド区切りOFS
文字を|~^
。これにより、出力フィールド間に挿入することを心配する必要がなくなります。入力フィールド区切り文字FS
は、この文字列に一致する正規表現に設定されます。
次に、3つの主要なコードブロックがあります。
1つは行を解析するために使用されます
H
。そのうちの1つだけがあり、最初に発生すると仮定します。これは単にヘッダー行を変数に格納しますheader
。一つは、
R
ライン解析のためのものです。各レコードには、3番目のフィールドで出力ファイル名として使用する必要がある日付が含まれています。それはあなたと同じように解析されます。その日付の合計が累積され、カウンタが増加します。カウンタが1の場合、つまり特定の日付を最初に見た場合は、その日付に関連する出力ファイルにヘッダを書き込みます。次に、現在のレコードをファイルに書き込みます。
最後のブロックは行を
T
解析します。そのうちの1つだけがあり、最後に表示されるとします。これは、単に各個々の日付の累積合計と数を、元の行の一部のデータT
とともにその日付に関連するファイルに出力します。
ランダムに大きな数字をサポートします(例:他の場所で数字を保存するのに100ビット以上が必要でオーバーフローする場合(の整数)、任意精度計算機を「コプロセス」(コンピューティングサービス)awk
として使用します。bc
行はsum[name] += $4
次に置き換えられます。
if (sum[name] == "") sum[name] = 0
printf "%s + %s\n", sum[name], $4 |& "bc"
"bc" |& getline sum[name]
これにはGNU awk
(ほとんどのUnixシステムで何らかの方法で利用可能)が必要です。
これが行うことは、現在の日付の合計がまだない場合は、まず現在の日付の合計をゼロに初期化することです。私たちがこれを行う理由は、初期合計を提供する必要があるからです0
。bc
bc
次に、awk
GNU固有のパイプを使用して評価する必要がある式を印刷して|&
補助プロセスに書き込みます。このbc
ユーティリティは、スクリプトと並列に起動し、実行され、計算を実行し、awk
別getline
のパイプの出力を直接 。bc
|&
sum[name]
私が理解しているように、GNUは各合計ごとに別々のプロセスを作成するのではなく、awk
共同プロセスとして実行されるプロセスを維持します。したがって、これはローカルで計算を実行するよりも遅いですが、合計ごとに別々の計算を生成するよりもはるかに高速です。bc
bc
awk
bc
与えられたデータに対して、次の2つのファイルが生成される。
$ cat 2019-03-05.txt
H|~^20200425|~^abcd|~^sum
R|~^abc|~^2019-03-05T12:33:52.27|~^105603.042|~^2018-10-23T12:33:52.27|~^aus
R|~^abc|~^2019-03-05T12:33:52.27|~^2054.026|~^2018-10-24T12:33:52.27|~^usa
R|~^abc|~^2019-03-05T12:33:52.27|~^30.00|~^2018-08-05T12:33:52.27|~^ddd
R|~^abc|~^2019-03-05T12:33:52.27|~^20.00|~^2018-07-23T12:33:52.27|~^audg
T|~^20200425|~^4|~^xxx|~^107707.068
$ cat 2019-03-06.txt
H|~^20200425|~^abcd|~^sum
R|~^abc|~^2019-03-06T12:33:52.27|~^123562388.23456|~^2018-04-12T12:33:52.27|~^hhh
R|~^abc|~^2019-03-06T12:33:52.27|~^10.00|~^2018-09-11T12:33:52.27|~^virginia
R|~^abc|~^2019-03-06T12:33:52.27|~^15.03|~^2018-10-23T12:33:52.27|~^jjj
R|~^abc|~^2019-03-06T12:33:52.27|~^10.04|~^2018-04-08T12:33:52.27|~^jj
T|~^20200425|~^4|~^xxx|~^123562423.30456