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

jan*_*ard 6 awk numeric-data

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

那么如何在距离场中检查数字何时小于前一个记录,以便从那时起将其添加到所有内容中等等?

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

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

这是我用来连接文件并保留一个标题的 awk one-liner:

awk '(NR == 1) || (FNR > 1)' *.csv > all.csv
Run Code Online (Sandbox Code Playgroud)

您可以在下面看到每个新工作表上一个文件末尾的数字如何重置为 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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

输出应该是:

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
Run Code Online (Sandbox Code Playgroud)

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

use*_*446 1

您应该发布一些示例行和您当前的脚本以获得准确的答案。
我不会比较数字是否较小,而是在添加偏移量 [第一个文件为 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
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)

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

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