使用 bash 解析 ICS 文件

Sab*_*gon 5 bash icalendar parsing file

这是一个谷歌日历 ics 文件。

\n\n

我每次都会下载它来检查是否有新的比赛事件被添加或更改,并且我出现在IRC上。

\n\n

我需要转换这样的文件:

\n\n
BEGIN: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\n
Run Code Online (Sandbox Code Playgroud)\n\n

到

\n\n
New 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)\n
Run Code Online (Sandbox Code Playgroud)\n\n

我需要使用 bash 脚本进行转换。\n我必须得到:

\n\n

DTSTART\n已创建\n最后修改\n位置\n摘要

\n\n

我需要比较 CREATED 和 LAST-MODIFIED

\n\n

伪代码 :

\n\n
if (created = LastModified)\nthen \n     echo createdevent\nelse\n     echo lastModifiedEvent\nfi\n
Run Code Online (Sandbox Code Playgroud)\n

Cha*_*ffy 5

本机 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\n
Run Code Online (Sandbox Code Playgroud)\n\n

...哪里handle_event有一个函数可以完成您关心的实际工作。例如,可能如下所示:

\n\n
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}\n
Run Code Online (Sandbox Code Playgroud)\n\n

使用给定的输入文件和上面的脚本,bash parse-ics <test.ics会产生以下输出(使用我当前的区域设置、时区和语言):

\n\n
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)\n
Run Code Online (Sandbox Code Playgroud)\n

  • @SaberPendragon,zsh 不是 bash。如果您想要 zsh 的答案,请不要在问题标题中添加“with bash”。 (2认同)

JNe*_*ill 5

awk对于这样的东西很有用。以下内容可以放置在新文件 (ics.awk) 中:

\n\n
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}\n
Run Code Online (Sandbox Code Playgroud)\n\n

您可以像这样执行它:

\n\n
awk -F":" -f ics.awk yourfile.ics\n
Run Code Online (Sandbox Code Playgroud)\n\n

这用冒号分割文件中的字段,并且 awk 脚本逐行处理文件。它在找到值时捕获值,然后在找到带有“END”的行时打印它们。

\n\n

上面的脚本将使您接近:

\n\n
New 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)\n
Run Code Online (Sandbox Code Playgroud)\n