2개의 열이 있는 텍스트 파일이 있습니다. 첫 번째 항목에는 날짜(DD/MM/YYYY)가 포함되고 두 번째 항목에는 숫자가 포함됩니다. 다음과 같습니다.
15/01/1945 105.0
16/01/1945 4.2
17/01/1945 3.0
31/01/1945 12.0
01/02/1945 3.0
02/02/1945 125.0
05/02/1945 0.3
다음 조건으로 파일을 채워야 합니다.
- 첫 번째 날짜 1945년 1월 1일
- 마지막 날짜 2021년 12월 31일
- 날짜는 연속되어야 하며 행 사이에는 하루가 있어야 합니다.
- 날짜가 누락된 경우 올바른 날짜와 숫자(99.0)로 라인을 완성해야 합니다.
따라서 최종 파일은 다음과 같아야 합니다.
01/01/1945 -99.0
02/01/1945 -99.0
03/01/1945 -99.0
04/01/1945 -99.0
05/01/1945 -99.0
06/01/1945 -99.0
07/01/1945 -99.0
08/01/1945 -99.0
09/01/1945 -99.0
10/01/1945 -99.0
11/01/1945 -99.0
12/01/1945 -99.0
13/01/1945 -99.0
14/01/1945 -99.0
15/01/1945 105.0
16/01/1945 4.2
17/01/1945 3.0
18/01/1945 -99.0
19/01/1945 -99.0
20/01/1945 -99.0
21/01/1945 -99.0
22/01/1945 -99.0
23/01/1945 -99.0
24/01/1945 -99.0
25/01/1945 -99.0
26/01/1945 -99.0
27/01/1945 -99.0
28/01/1945 -99.0
29/01/1945 -99.0
30/01/1945 -99.0
31/01/1945 12.0
01/02/1945 3.0
02/02/1945 125.0
03/02/1945 -99.0
04/02/1945 -99.0
05/02/1945 0.3
06/02/1945 -99.0
07/02/1945 -99.0
...
30/12/2021 -99.0
31/12/2021 -99.0
Fortran 프로그램을 사용해 보았지만 작동하지 않습니다. awk나 sed 또는 둘 다를 사용하는 것이 가능하다고 생각합니다.
Ed의 스크립트를 읽었을 때 얻은 내용은 다음과 같습니다.
meteo@poniente:/datos$ cat awk.script
#!/bin/bash
cat tst.awk
awk { dates2vals[$1] = $2 }
END {
begDate = "01/01/1945"
endDate = "31/12/2000"
begSecs = mktime(gensub("(.*)/(.*)/(.*)","\\3 \\2 \\1 12 00 00",1,begDate))
daySecs = 24 * 60 * 60
for (curSecs=begSecs; curDate!=endDate; curSecs+=daySecs) {
curDate = strftime("%d/%m/%Y",curSecs)
print curDate, (curDate in dates2vals ? dates2vals[curDate] : "-99.0")
}
}
Ed의 스크립트를 실행하면 다음과 같은 결과가 나옵니다.
meteo@poniente:/datos$ ./tst.awk
01/01/1946 3.0
02/01/1946 14.2
...
14/11/2021 0.0
15/11/2021 0.0
16/11/2021 0.0
17/11/2021 0.0
18/11/2021 0.0
19/11/2021 0.0
20/11/2021 0.0
21/11/2021 0.0
22/11/2021 54.1
23/11/2021 -99.0
24/11/2021 27.4
25/11/2021 0.0
29/11/2021 0.0
30/11/2021 0.0
awk: line ord.:1: {
awk: line ord.:1: ^ unexpected newline or end of string
./awk.script: line 4: END: command not found
./awk.script: line 5: begDate: command not found
./awk.script: line 6: endDate: command not found
./awk.script: line 7: syntax error near unexpected element `('
./awk.script: line 7: ` begSecs = mktime(gensub("(.*)/(.*)/(.*)","\\3 \\2 \\1 12 00 00",1,begDate))'
meteo@poniente:/datos$
답변1
seq
(epoch 초 단위: start, delta=1day, end) 및 date
기본값 -f
을 사용 -99.0
하고 가능한 경우 다음으로 바꿔서 긴 목록을 만들어 보십시오 awk
.
seq -f"@%.0f" -- -788878800 86400 1640905200 | date -uf- +"%d/%m/%Y -99.0" | awk 'FNR==NR {A[$1] = $2; next} $1 in A {$2 = A[$1]} 1' file -
01/01/1945 -99.0
02/01/1945 -99.0
.
.
.
14/01/1945 -99.0
15/01/1945 105.0
16/01/1945 4.2
17/01/1945 3.0
18/01/1945 -99.0
19/01/1945 -99.0
20/01/1945 -99.0
21/01/1945 -99.0
22/01/1945 -99.0
23/01/1945 -99.0
24/01/1945 -99.0
25/01/1945 -99.0
26/01/1945 -99.0
27/01/1945 -99.0
28/01/1945 -99.0
29/01/1945 -99.0
30/01/1945 -99.0
31/01/1945 12.0
01/02/1945 3.0
02/02/1945 125.0
03/02/1945 -99.0
04/02/1945 -99.0
05/02/1945 0.3
06/02/1945 -99.0
07/02/1945 -99.0
08/02/1945 -99.0
09/02/1945 -99.0
10/02/1945 -99.0
.
.
.
28/12/2021 -99.0
29/12/2021 -99.0
30/12/2021 -99.0
답변2
GNU awk를 사용하여 시간 함수를 구현합니다.
$ cat tst.awk
{ dates2vals[$1] = $2 }
END {
begDate = "01/01/1945"
endDate = "31/12/2021"
begSecs = mktime(gensub("(.*)/(.*)/(.*)","\\3 \\2 \\1 12 00 00",1,begDate))
daySecs = 24 * 60 * 60
for (curSecs=begSecs; curDate!=endDate; curSecs+=daySecs) {
curDate = strftime("%d/%m/%Y",curSecs)
print curDate, (curDate in dates2vals ? dates2vals[curDate] : "-99.0")
}
}
$ awk -f tst.awk file | wc -l
28124
$ awk -f tst.awk file | head -5
01/01/1945 -99.0
02/01/1945 -99.0
03/01/1945 -99.0
04/01/1945 -99.0
05/01/1945 -99.0
$ awk -f tst.awk file | tail -5
27/12/2021 -99.0
28/12/2021 -99.0
29/12/2021 -99.0
30/12/2021 -99.0
31/12/2021 -99.0
$ awk -f tst.awk file | grep -v '99.0'
15/01/1945 105.0
16/01/1945 4.2
17/01/1945 3.0
31/01/1945 12.0
01/02/1945 3.0
02/02/1945 125.0
05/02/1945 0.3