Sab*_*gon 5 bash icalendar parsing file
这是一个谷歌日历 ics 文件。
\n\n我每次都会下载它来检查是否有新的比赛事件被添加或更改,并且我出现在IRC上。
\n\n我需要转换这样的文件:
\n\nBEGIN:VEVENT\nDTSTART:20160612T201000Z\nDTEND:20160612T211000Z\nDTSTAMP:20160519T200239Z\nUID:xxxxxxxxxxxxxxxxxx@google.com\nCREATED:20160518T153226Z\nDESCRIPTION:\nLAST-MODIFIED:20160518T153226Z\nLOCATION:OCS Choc\nSEQUENCE:0\nSTATUS:CONFIRMED\nSUMMARY:Ash vs Evil Dead Saison 1 Episode 9 & 10\nTRANSP:OPAQUE\nEND:VEVENT\nBEGIN:VEVENT\nDTSTART;TZID=Europe/Brussels:20160611T203500\nDTEND;TZID=Europe/Brussels:20160611T233500\nDTSTAMP:20160519T202440Z\nUID:xxxxxxxx@google.com\nRECURRENCE-ID;TZID=Europe/Brussels:20160611T203500\nCREATED:20160503T144152Z\nDESCRIPTION:\nLAST-MODIFIED:20160518T123213Z\nLOCATION:RTS Un (Suisse)\nSEQUENCE:1\nSTATUS:CONFIRMED\nSUMMARY:The Mysteries Of Laura Saison 2 Episode 1 \xc3\xa0 4\nTRANSP:TRANSPARENT\nEND:VEVENT\nRun Code Online (Sandbox Code Playgroud)\n\n到
\n\nNew Events Created :\ndim. juin 12 20:10 Ash vs Evil Dead Saison 1 Episode 9 & 10 - OCS Choc\n\nLast Modified Event :\nsam. juin 11 20:35 The Mysteries Of Laura Saison 2 Episode 1 \xc3\xa0 4 - RTS Un (Suisse)\nRun Code Online (Sandbox Code Playgroud)\n\n我需要使用 bash 脚本进行转换。\n我必须得到:
\n\nDTSTART\n已创建\n最后修改\n位置\n摘要
\n\n我需要比较 CREATED 和 LAST-MODIFIED
\n\n伪代码 :
\n\nif (created = LastModified)\nthen \n echo createdevent\nelse\n echo lastModifiedEvent\nfi\nRun Code Online (Sandbox Code Playgroud)\n
本机 bash 实现(对于 shell 版本 4.0 或更高版本 - 旧版本缺少关联数组)将如下所示:
\n\n#!/bin/bash\n\nhandle_event() {\n : # put a definition of your intended logic here\n}\n\ndeclare -A content=( ) # define an associative array (aka map, aka hash)\ndeclare -A tzid=( ) # another associative array for timezone info\n\nwhile IFS=: read -r key value; do\n value=${value%$\'\\r\'} # remove DOS newlines\n if [[ $key = END && $value = VEVENT ]]; then\n handle_event # defining this function is up to you; see suggestion below\n content=( )\n tzid=( )\n else\n if [[ $key = *";TZID="* ]]; then\n tzid[${key%%";"*}]=${key##*";TZID="}\n fi\n content[${key%%";"*}]=$value\n fi\ndone\nRun Code Online (Sandbox Code Playgroud)\n\n...哪里handle_event有一个函数可以完成您关心的实际工作。例如,可能如下所示:
local_date() {\n local tz=${tzid[$1]}\n local dt=${content[$1]}\n if [[ $dt = *Z ]]; then\n tz=UTC\n dt=${dt%Z}\n fi\n shift\n\n if [[ $dt = *T* ]]; then\n dt="${dt:0:4}-${dt:4:2}-${dt:6:2}T${dt:9:2}:${dt:11:2}"\n else\n dt="${dt:0:4}-${dt:4:2}-${dt:6:2}"\n fi\n\n # note that this requires GNU date\n date --date="TZ=\\"$tz\\" $dt" "$@"\n}\n\nhandle_event() {\n if [[ "${content[LAST-MODIFIED]}" = "${content[CREATED]}" ]]; then\n echo "New Event Created"\n else\n echo "Modified Event"\n fi\n printf \'%s\\t\' "$(local_date DTSTART)" "${content[SUMMARY]}" "${content[LOCATION]}"; echo\n}\nRun Code Online (Sandbox Code Playgroud)\n\n使用给定的输入文件和上面的脚本,bash parse-ics <test.ics会产生以下输出(使用我当前的区域设置、时区和语言):
New Event Created\nSun Jun 12 15:10:00 CDT 2016 Ash vs Evil Dead Saison 1 Episode 9 & 10 OCS Choc\nModified Event\nSat Jun 11 15:35:00 CDT 2016 The Mysteries Of Laura Saison 2 Episode 1 \xc3\xa0 4 RTS Un (Suisse)\nRun Code Online (Sandbox Code Playgroud)\n
awk对于这样的东西很有用。以下内容可以放置在新文件 (ics.awk) 中:
BEGIN{OFS=" "}\n$1=="DTSTART"{DTSTART=$2}\n$1=="CREATED"{CREATED=$2}\n$1=="LAST-MODIFIED"{LASTMODIFIED=$2}\n$1=="SUMMARY"{SUMMARY=$2}\n$1=="LOCATION"{LOCATION=$2}\n$1=="END"{\n if (CREATED==LASTMODIFIED)\n print "\\nNew Event Created"\n else\n print "\\nLast Modified Event"\n\n print DTSTART,SUMMARY,LOCATION\n}\nRun Code Online (Sandbox Code Playgroud)\n\n您可以像这样执行它:
\n\nawk -F":" -f ics.awk yourfile.ics\nRun Code Online (Sandbox Code Playgroud)\n\n这用冒号分割文件中的字段,并且 awk 脚本逐行处理文件。它在找到值时捕获值,然后在找到带有“END”的行时打印它们。
\n\n上面的脚本将使您接近:
\n\nNew Event Created\n20160612T201000Z Ash vs Evil Dead Saison 1 Episode 9 & 10 OCS Choc\n\nLast Modified Event\n20160612T201000Z The Mysteries Of Laura Saison 2 Episode 1 \xc3\xa0 4 RTS Un (Suisse)\nRun Code Online (Sandbox Code Playgroud)\n