2016-04-15 10 views
0

Ich mag die zusammenhängenden Bereiche gegeben eine Reihe von Terminen für Tag findenFinding Contiguous Rang

angesichts dem folgende Beispiel

2016-01-01 
2016-01-02 
2016-01-03 
2016-01-04 
2016-01-05 
2016-01-06 
2016-01-08 
2016-01-09 
2016-01-10 
2016-01-11 
2016-01-12 
2016-01-15 
2016-01-16 
2016-01-17 
2016-01-20 
2016-01-21 
2016-01-30 
2016-01-31 
2016-02-01 

Ich erwarte, dass das folgende Ergebnis

2016-01-01-2016-01-06 
2016-01-08-2016-01-12 
2016-01-15-2016-01-17 
2016-01-20-2016-01-21 
2016-01-30-2016-01-31 
2016-02-01-2016-02-01 

Ich habe bin schon auf this Frage gestoßen, die fast das Gegenteil von dem ist, was ich will, aber mit ganzen Zahlen. Ich habe folgendes formuliert, was mit Ganzzahlen funktioniert.

awk 'NR==1 {l=$1; n=$1} {if ($1==n){n=$1+1} else{print l"-"n-1; l=$1 ;n=$1+1} } END {print l"-"$1}' file.txt 
+0

hmmm, auch wenn Sie es schaffen, tu das, du hast noch ein anderes Problem zu lösen, was wenn der Monat 30 Tage hat? der letzte Tag (also der 30.) würde ebenfalls gedruckt werden, da man denkt, dass der nächste Tag nicht im Text existiert. Und wenn der Monat 29 oder 31 Tage hat, müssen Sie dem Skript "erzählen", welcher Monat wie viele Tage hat, damit es weiß, wann der letzte Tag des Monats nicht gedruckt wird. – hedgehog

+0

Wenn wir eine Monatsgrenze überschreiten, ist es in Ordnung, einen neuen Bereich zu beginnen. Ich habe das Beispiel und die Ergebnisse aktualisiert, um dies zu berücksichtigen. Auch wenn das Datum in einen Ordinalwert umgewandelt werden kann, wäre dies kein Problem – Mark

Antwort

0

mit GNU awk für mktime():

$ cat tst.awk 
BEGIN { FS=OFS="-" } 
{ currSecs = mktime($1" "$2" "$3" 0 0 0") } 
(currSecs - prevSecs) > (24*60*60) { 
    if (NR>1) { 
     print startDate, prevDate 
    } 
    startDate = $0 
} 
{ prevSecs = currSecs; prevDate = $0 } 
END { print startDate, prevDate } 

$ awk -f tst.awk file 
2016-01-01-2016-01-06 
2016-01-08-2016-01-12 
2016-01-15-2016-01-17 
2016-01-20-2016-01-21 
2016-01-30-2016-02-01 

Mit jedem awk, wenn Sie Bereiche neu zu starten, wenn Monaten Änderung (in Ihrer erwarteten Ausgabe und den Kommentar unter Ihrer Frage so offensichtlich) nicht kümmern:

$ cat tst.awk 
BEGIN { FS=OFS="-" } 
{ currYrMth = $1 FS $2; currDay = $3 } 
(currYrMth != prevYrMth) || ((currDay - prevDay) > 1) { 
    if (NR>1) { 
     print startDate, prevDate 
    } 
    startDate = $0 
} 
{ prevYrMth = currYrMth; prevDay = currDay; prevDate = $0 } 
END { print startDate, prevDate } 

$ awk -f tst.awk file 
2016-01-01-2016-01-06 
2016-01-08-2016-01-12 
2016-01-15-2016-01-17 
2016-01-20-2016-01-21 
2016-01-30-2016-01-31 
2016-02-01-2016-02-01 
0

Wenn Sie GNU Awk haben, können Sie seine time functions verwenden.

gawk -F - 'NR==1 || $1 "-" $2 "-" $3 != following { 
    if (following != "") print start "-" latest; 
    start = $1 "-" $2 "-" $3 
    this = mktime($1 " " $2 " " $3 " 0 0 0") 
    } 
    { 
    this += 24*60*60 
    following = strftime("%F", this) 
    latest = $1 "-" $2 "-" $3 } 
    END { if (start != latest) print start "-" latest }' filename 

Einheit Bereiche wie „2016-04-15-2016-04-15“ wird gedruckt, die ein bisschen von einer Warze, aber leicht zu beheben, wenn Sie benötigen. Auch der END Block hat in diesem Fall einen Fehler, aber auch hier sollte man zumindest anfangen.

0

gawk:

#!/bin/awk -f 
BEGIN{ 
     FS="-" 
} 
{ 
     a[NR]=mktime($1" "$2" "$3" 0 0 0") 
     b[NR]=$2; 
     if ((a[NR-1]+86400) != a[NR] || b[NR-1]!=b[NR]) { 
       if(NR!=1){ 
         print s" - "strftime("%Y-%m-%d",a[NR-1]) 
       }; 
       s=$0 
     } 
} 
END{ 
     print s" - "$0 
} 

Array erstellen a mit Index NR und Wert als epochtime von $ 0 unter Verwendung von AWK Zeitfunktion mktime abgeleitet.

Array b mit Index NR und Wert als Monat in $2 wenn entweder Epoche Zeit von den letzten Zeile + 86400 (1 Tag) nicht gleich Zeit in der aktuellen Zeile oder Monat in der vorherige Zeile und die aktuelle Zeile unterscheidet sich Epoche, mit Ausnahme der ersten Zeile, Druckwert in s" - "strftime("%Y-%m-%d",a[NR-1] und s neu zuweisen, die das Startdatum

END mit $0

ist: drucken Sie die letzte Startzeit s und letzte Zeile