文件1:

文件1:

文件1:

H|~^20200425|~^abcd|~^sum
R|~^abc|~^2019-03-06T12:33:52.27|~^1000123.34567|~^2018-04-12T12:33:52.27|
R|~^abc|~^2019-03-05T12:33:52.27|~^111930.02876|~^2018-10-23T12:33:52.27|
R|~^abc|~^2019-03-05T12:33:52.27|~^2112320.028|~^2018-10-24T12:33:52.27|
R|~^abc|~^2019-03-06T12:33:52.27|~^12230.0809|~^2018-09-11T12:33:52.27|
R|~^abc|~^2019-03-05T12:33:52.27|~^3076543789.00878|~^2018-08-05T12:33:52.27|
R|~^abc|~^2019-03-06T12:33:52.27|~^156655.0389|~^2018-10-23T12:33:52.27|
R|~^abc|~^2019-03-06T12:33:52.27|~^10453.0489|~^2018-04-08T12:33:52.27|
R|~^abc|~^2019-03-05T12:33:52.27|~^20654.0907|~^2018-07-23T12:33:52.27|
T|~^20200425|~^abcd|~^3424365.66183

文件2:

H|~^20200426|~^abcd|~^sum
R|~^abc|~^2019-03-07T12:33:52.27|~^10.347|~^2018-04-12T12:33:52.27|
R|~^abc|~^2019-03-08T12:33:52.27|~^111.06|~^2018-10-23T12:33:52.27|
R|~^abc|~^2019-03-05T12:33:52.27|~^2112.08|~^2018-10-24T12:33:52.27|
R|~^abc|~^2019-03-06T12:33:52.27|~^12230.089|~^2018-09-11T12:33:52.27|
R|~^abc|~^2019-03-04T12:33:52.27|~^30769.078|~^2018-08-05T12:33:52.27|
R|~^abc|~^2019-03-06T12:33:52.27|~^155.09|~^2018-10-23T12:33:52.27|
R|~^abc|~^2019-03-03T12:33:52.27|~^10.89|~^2018-04-08T12:33:52.27|
R|~^abc|~^2019-03-05T12:33:52.27|~^206.07|~^2018-07-23T12:33:52.27|
T|~^20200426|~^abcd|~^155604.704

我需要获取从“R”开始的记录的第四个字段中的总金额之和。我希望将所有行的金额总和存储在变量中。求和后,它应该正确捕获所有小数点。以“T”开头的预告片记录在最后一个字段中有总和输出以供参考。

答案1

分离器是一个挑战

我想出了

awk -F '[|^]' '$1 == "R" { s+=$7 ; } $1 == "T" {  printf "Sum %.5f\n",s}'

给予

Sum 3079968154.67061

在哪里

  • -F '[|^]'告诉 awk 使用|^作为字段分隔符
  • $1 == "R" { s+=$7 ; }s如果第一个字段是,则在第 7 个字段中求和R
  • $1 == "T" { printf "Sum %.5f\n",s}打印总计,包括5位数字

调整输出精度,可以使用神秘的 printf(3) 选项

awk -v prec=3 -F '[|^]' '$1 == "R" { s+=$7 ; } 
     $1 == "T" { print ; printf "Sum %.*f\n",prec,s}' 

给予

Sum 3079968154.671

在哪里

  • -v prec=3给出精度
  • *告诉"Sum %.*f\n"printf 使用 arg 作为 %f 的精度。

可以计算精度。

awk  -F '[|^]' '$1 == "R" { s+=$7 ; } 
                $1 == "T" { print ; 
                            prec=length($7)-index($7,".");  
                            printf "t:%s, Sum %.*f\n",$7,prec,s}'

给出两个示例文件

T|~^20200425|~^abcd|~^3424365.66183
t:3424365.66183, Sum 3079968154.67061

T|~^20200426|~^abcd|~^155604.704
t:155604.704, Sum 45604.704

请注意,它不适用于负精度(prec=-2 四舍五入到百位数)。

关于精度的注意事项:

根据https://en.wikipedia.org/wiki/Double- precision_floating-point_format精度为 52 位,即大约 15 位数字。上面的数字可能是精确总和的近似值(由于3076543789.00878宽度为 15 位)。

答案2

如果通过

正确捕获所有小数点

您的意思是您希望以任何项的最大精度打印总和,那么您可能需要跟踪精度 - 例如:

$ awk -F'\\|~\\^' '
    $1=="R"{sum+=$4; if(match($4,/\.[0-9]+/) && RLENGTH-1>p) {p=RLENGTH-1}} 
    END{printf "%.*f\n",p,sum}
  ' File2
  45604.704

$ awk -F'\\|~\\^' '
    $1=="R"{sum+=$4; if(match($4,/\.[0-9]+/) && RLENGTH-1>p) {p=RLENGTH-1}} 
    END{printf "%.*f\n",p,sum}
  ' File1
  3079968154.67061

可能有更好的方法来提取精度 - 正则表达式匹配只是我首先想到的。

相关内容