simplify and improve portability across mawk, gawk, nawk, busybox awk... - ics2txt - convert icalendar .ics file to plain text HTML git clone git://bitreich.org/ics2txt git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/ics2txt DIR Log DIR Files DIR Refs DIR Tags DIR README --- DIR commit 24985c575e833254adb79215584947a601569ea1 DIR parent c6606df0960a765824c000aeb54e21691bcc94bb HTML Author: Josuah Demangeon <me@josuah.net> Date: Thu, 25 Jun 2020 21:11:17 +0200 simplify and improve portability across mawk, gawk, nawk, busybox awk... Diffstat: M README | 33 +++++++++++++++---------------- M ics2tsv | 32 ++++++++++++------------------- M tcal2tsv | 12 ++++++------ M tsv2tcal | 4 ++-- 4 files changed, 36 insertions(+), 45 deletions(-) --- DIR diff --git a/README b/README @@ -1,7 +1,5 @@ -ICS2TSV(1) General Commands Manual ICS2TSV(1) - NAME - ics2tsv – convert ics file to simpler tsv or txt formats + ics2txt – convert ics file to simpler tsv or txt formats SYNOPSIS ics2txt <file.ics >file.txt @@ -13,31 +11,34 @@ SYNOPSIS tsv2ics <file.tsv >file.ics DESCRIPTION - ics2tsv is set of awk scripts to deal with iCal (.ics) format to publish, + ics2txt is set of awk scripts to deal with iCal (.ics) format to publish, display and convert *.ics files, though a simple central TSV format. They all read from either stdin or the file passed as argument, and write to stdout. - file.tsv files have one line per event, all with the following fields, - separated by one tab: - 1. Begining (epoch) - 2. End (epoch) - 3. Category - 4. Location - 5. Summary - 6. Description + file.tsv have one line per event, with the first line declaring fields + order and presence, among: + “beg” Begining of event (epoch) + “end” End of event (epoch) + “cat” Category + “loc” Location + “sum” Summary + “des” Description EXAMPLES - Convert a calendar from HTTP .ics to custom .txt sorted by beginning - date: + Convert a calendar from HTTP .ics to custom .txt sorted by start date: curl $url.ics | ics2tsv | sort -n -k 1,1 | tsv2txt Convert a custom .txt format back to an .ics file and publish it: tcal2tsv cal.txt | tsv2ics | ssh www@$host 'cat >/var/www/cal.ics' Split an file according to the category, saved as .tsv: - tcal2tsv cal.txt | awk -F '\t' '{ f = $3".tsv"; print >>f }' + + ics2tsv cal.txt | awk -F '\t' ' + NR == 1 { for (i = 1; i <= NF; i++) F[$i] = i; next } + { print >>($F["cat"]".tsv") } + ´ SEE ALSO cal(1), calendar(1), date(1), sort(1) @@ -48,5 +49,3 @@ STANDARDS AUTHORS Josuah Demangeon <me@josuah.net> - -OpenBSD 6.6 March 1, 2020 OpenBSD 6.6 DIR diff --git a/ics2tsv b/ics2tsv @@ -44,49 +44,41 @@ function ical_to_epoch(str, offset, function print_event(ev, fields, i) { - for (i = 1; i <= fields["len"]; i++) + for (i = 1; i in fields; i++) printf("%s%s", (i > 1 ? "\t" : ""), ev[fields[i]]) printf("\n") } BEGIN { FIELDS = "DTSTART DTEND CATEGORIES LOCATION SUMMARY DESCRIPTION" - fields["len"] = split(FIELDS, fields, " ") + split(FIELDS, fields, " ") # by default: "CATEGORIES" -> "cat", "LOCATION" -> "loc"... translate["DTSTART"] = "beg" translate["DTEND"] = "end" - "date +%z" | getline offset_str + "date +%z" | getline close("date +%z") - hour = substr($0, 4, 2) - min = substr($0, 6, 2) - tzoffset = substr(zone, 3, 1) hour * 3600 + min * 60 + TZ = substr($0, 3, 1) substr($0, 4, 2)*3600 + substr($0, 6, 2)*60 FS = "[:;]" - for (i = 1; i <= fields["len"]; i++) { + for (i = 1; i in fields; i++) { if (!(s = translate[fields[i]])) s = tolower(substr(fields[i], 1, 3)) printf("%s%s", (i > 1 ? "\t" : ""), s) } - printf("\n") } +/^ / { + ev[type] = ev[type] substr($0, 2, length($0) - 1) + next +} + { - gsub("\r", "") - gsub("\t", "\\\\t") - gsub("^ *", "") - gsub(" *$", "") - - if (match($0, "^ ")) { - ev[type] = ev[type] substr($0, 2, length($0) - 1) - } else { - type = $1 - i = index($0, ":") - ev[type] = substr($0, i + 1, length($0) - i) - } + i = index($0, ":") + ev[$1] = substr($0, i + 1, length($0) - i) } /^END:VEVENT/ { DIR diff --git a/tcal2tsv b/tcal2tsv @@ -42,9 +42,9 @@ function text_to_epoch(str, tz, BEGIN { FIELDS = "beg end cat loc sum des" - fields["len"] = split(FIELDS, fields, " ") + split(FIELDS, fields, " ") - for (i = 1; i <= fields["len"]; i++) { + for (i = 1; i in fields; i++) { pos[fields[i]] = i printf("%s%s", (i > 1 ? "\t" : ""), fields[i]) } @@ -56,16 +56,16 @@ BEGIN { } /^TZ[+-]/ { - TZOFFSET = substr($1, 3, 1) substr($0, 4, 2)*3600 + substr($0, 6, 2)*60 + TZ = substr($1, 3, 1) substr($0, 4, 2)*3600 + substr($0, 6, 2)*60 while (getline && $0 ~ /^$/) continue } /^[0-9]+-[0-9]+-[0-9]+/ { if ("beg" in ev) - ev["end"] = text_to_epoch($0, TZOFFSET) + ev["end"] = text_to_epoch($0, TZ) else - ev["beg"] = text_to_epoch($0, TZOFFSET) + ev["beg"] = text_to_epoch($0, TZ) next } @@ -78,7 +78,7 @@ BEGIN { } /^$/ { - for (i = 1; i <= fields["len"]; i++) + for (i = 1; i in fields; i++) printf("%s%s", (i > 1 ? "\t" : ""), ev[fields[i]]) printf("\n") delete ev DIR diff --git a/tsv2tcal b/tsv2tcal @@ -43,13 +43,13 @@ function gmtime(sec, tm) function localtime(sec, tm, tz, h, m) { - return gmtime(sec + TZOFFSET, tm) + return gmtime(sec + TZ, tm) } BEGIN { "date +%z" | getline tz close("date +%z") - TZOFFSET = substr(tz, 1, 1) substr(tz, 2, 2)*3600 + substr(tz, 4, 2)*60 + TZ = substr(tz, 1, 1) substr(tz, 2, 2)*3600 + substr(tz, 4, 2)*60 print("TZ" tz)