AWK 数字が前の数字より小さい場合は、前の数字を現在の数字に追加してからその点から追加する方法

AWK 数字が前の数字より小さい場合は、前の数字を現在の数字に追加してからその点から追加する方法

GoPro距離データを含むフィールドがあります。ファイルを一緒にリンクする必要がありますが、ビデオファイルには設定された期間しかないため、各新しいcsvファイルの距離は0から始まります。

もしそうなら、その数が前のレコードよりも小さいときに距離フィールドをどのようにチェックして、それ以降のすべての項目に追加できますか?

可能であれば、時間フィールドを0から0.05ずつ増やす方法は?

私はこの問題を解決するためにいくつかのフォーラムでawkの質問を読むのに長い時間を費やしましたが、まだ成功していないので、ついに直接質問をしました。

これは、ファイルをリンクしてヘッダーを保持するために使用するawkの1行です。

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

以下では、各新しいワークシートでファイルの末尾の数字がゼロにリセットされる方法を示します。

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

もう1つは代わりにループと配列を使用します。

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

公開したヘッダー行がファイルに含まれていないとします(達成しやすいと思います)。
2番目は、すべてのフィールドを処理する必要があると仮定します。

必要に応じて、AWKスクリプト内の引用符内にない改行を含むすべてのスペースを省略できます(この場合、引用符/必須スペースはまったくありません)。 (セミコロンの一部を省略することも可能ですが、そうしたくありません。)

関連情報