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 스크립트에서 따옴표 안에 있지 않은 줄 바꿈을 포함하여 모든 공백을 생략할 수 있습니다(이 경우 따옴표/필수 공백이 전혀 없음). (세미콜론 중 일부를 생략하는 것도 가능하지만 그렇게 하고 싶지는 않습니다.)

관련 정보