AWK如果数字小于前一个数字,如何将前一个数字添加到当前数字,然后从那时起

AWK如果数字小于前一个数字,如何将前一个数字添加到当前数字,然后从那时起

有一个包含 GoPro 距离数据的字段。需要将文件连接在一起,但每个新 csv 文件的距离从 0 开始,因为视频文件只有设定的持续时间。

那么,如何在距离字段中检查该数字何时小于先前的记录,以便可以将其添加到此后的所有内容中,等等?

如果可能的话,时间字段如何从 0 以 0.05 的增量递增?

我花了很长时间在几个论坛上阅读 awk 问题试图解决这个问题,但还没有成功,所以我终于自己问这个问题了。

这是我用来连接文件并保留一个标头的 awk 单行代码:

awk '(NR == 1) || (FNR > 1)' *.csv > all.csv

下面您可以看到一个文件末尾的数字如何在每个新工作表上重置为 0。

csv 1 结尾:

Time    Feet          Meters        Miles       Kilometers
676.65  9723.24067    2963.643756   1.841523    2.963644
676.7   9723.983124   2963.870056   1.841663    2.96387
676.75  9724.694981   2964.08703    1.841798    2.964087
676.8   9725.429621   2964.310948   1.841937    2.964311
676.85  9726.20625    2964.547665   1.842085    2.964548
676.9   9726.936465   2964.770235   1.842223    2.96477
676.95  9727.547469   2964.956469   1.842339    2.964956

csv 2 的开头:

Time    Feet          Meters        Miles       Kilometers
0       0             0             0           0
0.05    0.687379      0.209513      0.00013     0.00021
0.1     1.469281      0.447837      0.000278    0.000448
0.15    2.223126      0.677609      0.000421    0.000678
0.2     2.965581      0.903909      0.000562    0.000904
0.25    3.736514      1.138889      0.000708    0.001139
0.3     4.530231      1.380814      0.000858    0.001381

输出应该是:

Time    Feet          Meters        Miles       Kilometers
676.65  9723.24067    2963.643756   1.841523    2.963644
676.7   9723.983124   2963.870056   1.841663    2.96387
676.75  9724.694981   2964.08703    1.841798    2.964087
676.8   9725.429621   2964.310948   1.841937    2.964311
676.85  9726.20625    2964.547665   1.842085    2.964548
676.9   9726.936465   2964.770235   1.842223    2.96477
676.95  9727.547469   2964.956469   1.842339    2.964956
677     9727.547469   2964.956469   1.842339    2.964956
677.05  9728.234848   2965.165982   1.842469    2.965166
677.1   9729.01675    2965.404306   1.842617    2.965404
677.15  9729.770595   2965.634078   1.84276     2.965634
677.2   9730.51305    2965.860378   1.842901    2.96586
677.25  9731.283983   2966.095358   1.843047    2.966095
677.3   9732.0777     2966.337283   1.843197    2.966337

再次非常感谢任何帮助。谢谢。

答案1

这是Python的解决方案,以防万一:

import fileinput
from decimal import *

def main():
    save_values = [Decimal(0.0) for n in range(5)]
    last_values = save_values.copy()

    header_shown = False

    for line in fileinput.input():
        line = line.strip()
        if line == "":
            continue
        if line.startswith("Time"):
            if not header_shown:
                print(line)
                header_shown = True
            continue
        (time, feet, meters, miles, kms) = [Decimal(x) for x in line.split()]
        if time == 0.0:
            save_values = last_values.copy()
            continue
        time += save_values[0]
        feet += save_values[1]
        meters += save_values[2]
        miles += save_values[3]
        kms += save_values[4]
        print("{}\t{}\t{}\t{}\t{}".format(time, feet, meters, miles, kms))
        last_values = [time, feet, meters, miles, kms]

if __name__ == "__main__":
    main()

它给出的输出略有不同,在您的输出中您有:

676.95  9727.547469   2964.956469   1.842339    2.964956
677     9727.547469   2964.956469   1.842339    2.964956

但我认为正确的输出应该是:

676.95  9727.547469 2964.956469 1.842339    2.964956
677.00  9728.234848 2965.165982 1.842469    2.965166

答案2

您应该发布一些示例行和您当前的脚本以获得准确的答案。
我不会比较数字是否较小,而是在添加偏移量 [第一个文件为 0] 后处理行时保存整体偏移量并调整偏移量。

例子: awk 'FNR==1&&ARGIND>1{distoffset=distnow}{$2+=distoffset;distnow=$2+$3;print $0;}'

假设您在字段 2 中有一个距离,在字段 3 中有当前条目的长度(这需要添加到前一个记录的距离,否则我假设文件的第一个记录与前一个文件的最后一个记录具有相同的距离。

对于您的其他问题,我不明白您想要什么。添加 0.05 增量也不是问题,但如果我不理解确切的要求,则无法告诉您如何操作。


因此,通过您提供的附加信息,我可以使我的示例更加完整。
首先是更详细的版本:

rm -f all.csv
awk '
FNR==1 {
 if (ARGIND>1) {
  timeoffset = timenow + 0.05;
  feetoffset = feetnow;
  metersoffset = metersnow;
  milesoffset = milesnow;
  kmeteroffset = kmeternow;
 } else {
  print $0;
 }
 next;
}
FNR>1{
 $1 += timeoffset; timenow = $1;
 $2 += feetoffset; feetnow = $2;
 $3 += metersoffset; metersnow = $3;
 $4 += milesoffset; milesnow = $4;
 $5 += kmeteroffset; kmeternow = $5;
 print $0;
}
' *.csv > all.csv

另一种使用循环和数组代替:

rm -f all.csv
awk '
FNR==1 {
 if (ARGIND>1) {
  for (cfn = 1; cfn <= NF; cfn++) {
   offsetvals[cfn] = savedvals[cfn];
  }
  offsetvals[1] += 0.05;
 } else {
  print $0;
 }
 next;
}
FNR>1{
 for (cfn = 1; cfn <= NF; cfn++) {
  $cfn += offsetvals[cfn];
  savedvals[cfn] = $cfn;
 }
 print $0;
}
' *.csv > all.csv

还有一个带有循环的版本,它更通用,可以重用于不应用于所有字段或应该动态化的文件:

rm -f all.csv
awk '
BEGIN {
 procfields["tm"] = 1;
 procfields["ft"] = 2; procfields["mt"] = 3;
 procfields["ml"] = 4; procfields["km"] = 5; 
}
FNR==1 {
 if (ARGIND>1) {
  for (fnname in procfields) {
   cfn = procfields[fnname];
   offsetvals[cfn] = savedvals[cfn];
  };
  offsetvals[procfields["tm"]] += 0.05;
 } else {
  print $0;
 }
 next;
}
FNR>1{
 for (fnname in procfields) {
  cfn = procfields[fnname];
  $cfn += offsetvals[cfn];
  savedvals[cfn] = $cfn;
 };
 print $0;
}
' *.csv > all.csv

所有假设您发布的标题行不包含在文件中(认为很容易实现)。
第二个假设所有字段都需要处理。

您可以根据需要省略所有空格,包括 AWK 脚本中不在引号内的换行符(在这种情况下,根本没有引号/需要的空格)。 (也可以省略一些分号,但我不想这样做。)

相关内容