2016-05-19 12 views
1

これはgoogleカレンダーのicsファイルです。bashでICSファイルを解析する

新しいプレイイベントが追加または変更されたかどうかを確認するたびにダウンロードし、IRCに表示されます。

BEGIN:VEVENT 
DTSTART:20160612T201000Z 
DTEND:20160612T211000Z 
DTSTAMP:20160519T200239Z 
UID:[email protected] 
CREATED:20160518T153226Z 
DESCRIPTION: 
LAST-MODIFIED:20160518T153226Z 
LOCATION:OCS Choc 
SEQUENCE:0 
STATUS:CONFIRMED 
SUMMARY:Ash vs Evil Dead Saison 1 Episode 9 & 10 
TRANSP:OPAQUE 
END:VEVENT 
BEGIN:VEVENT 
DTSTART;TZID=Europe/Brussels:20160611T203500 
DTEND;TZID=Europe/Brussels:20160611T233500 
DTSTAMP:20160519T202440Z 
UID:[email protected] 
RECURRENCE-ID;TZID=Europe/Brussels:20160611T203500 
CREATED:20160503T144152Z 
DESCRIPTION: 
LAST-MODIFIED:20160518T123213Z 
LOCATION:RTS Un (Suisse) 
SEQUENCE:1 
STATUS:CONFIRMED 
SUMMARY:The Mysteries Of Laura Saison 2 Episode 1 à 4 
TRANSP:TRANSPARENT 
END:VEVENT 

New Events Created : 
dim. juin 12 20:10 Ash vs Evil Dead Saison 1 Episode 9 & 10 - OCS Choc 

Last Modified Event : 
sam. juin 11 20:35 The Mysteries Of Laura Saison 2 Episode 1 à 4 - RTS Un (Suisse) 

に私はbashスクリプトで変換する必要があります。

は、私はこのようなファイルを変換する必要があります。 私が取得する必要があります:

をDTSTART が LAST-MODIFIED LOCATION 概要

を作成し、私が作成したとLAST-MODIFIED

擬似コード比較する必要があります。

if (created = LastModified) 
then 
    echo createdevent 
else 
    echo lastModifiedEvent 
fi 
+0

Ahh - 現地日が必要ですか?あなたのロケールは何ですか? –

+0

@ charles-duffy今日の日付で検索したい。 私の変数のベータリリーススクリプトにこれを使用しました: 'dateOfDay = $(date +%Y%m%d)' –

+0

あなたの出力は人間の言語で日付を表示します。それが本当にあなたの意図する出力の一部ですか、それとも今日のフィルタが重要なのですか? –

答えて

0

Aをネイティブbashの実装(シェルバージョン4.0以降では、古いバージョンには連想配列がありません)は次のようになります: handle_eventは、あなたが気に実際の作業を行う関数である

#!/bin/bash 

handle_event() { 
    : # put a definition of your intended logic here 
} 

declare -A content=() # define an associative array (aka map, aka hash) 
declare -A tzid=() # another associative array for timezone info 

while IFS=: read -r key value; do 
    value=${value%$'\r'} # remove DOS newlines 
    if [[ $key = END && $value = VEVENT ]]; then 
    handle_event # defining this function is up to you; see suggestion below 
    content=() 
    tzid=() 
    else 
    if [[ $key = *";TZID="* ]]; then 
     tzid[${key%%";"*}]=${key##*";TZID="} 
    fi 
    content[${key%%";"*}]=$value 
    fi 
done 

...。例えば、それは次のようになります。

local_date() { 
    local tz=${tzid[$1]} 
    local dt=${content[$1]} 
    if [[ $dt = *Z ]]; then 
    tz=UTC 
    dt=${dt%Z} 
    fi 
    shift 

    if [[ $dt = *T* ]]; then 
    dt="${dt:0:4}-${dt:4:2}-${dt:6:2}T${dt:9:2}:${dt:11:2}" 
    else 
    dt="${dt:0:4}-${dt:4:2}-${dt:6:2}" 
    fi 

    # note that this requires GNU date 
    date --date="TZ=\"$tz\" $dt" "[email protected]" 
} 

handle_event() { 
    if [[ "${content[LAST-MODIFIED]}" = "${content[CREATED]}" ]]; then 
    echo "New Event Created" 
    else 
    echo "Modified Event" 
    fi 
    printf '%s\t' "$(local_date DTSTART)" "${content[SUMMARY]}" "${content[LOCATION]}"; echo 
} 

あなたの入力ファイルと上記のスクリプトでは、bash parse-ics <test.icsは(私の現在のロケール、タイムゾーンと言語を持つ)次の出力が得られます。

New Event Created 
Sun Jun 12 15:10:00 CDT 2016 Ash vs Evil Dead Saison 1 Episode 9 & 10  OCS Choc 
Modified Event 
Sat Jun 11 15:35:00 CDT 2016 The Mysteries Of Laura Saison 2 Episode 1 à 4 RTS Un (Suisse) 
+0

このソリューションは私のzshでは機能しません –

+1

@SaberPendragon、zshはbashではありません。 zshの回答が必要な場合は、質問タイトルに "with bash"を入れないでください。 –

+0

私はGNU bash、バージョン4.3.30(1)-release(x86_64-pc-linux-gnu)とzsh 5.0.7(x86_64-pc-linux-gnu)を持っています。間違えて申し訳ありません.. –

2

awkこのようなものには便利です。以下は、新しいファイル(ics.awk)に配置することができます。

BEGIN{OFS=" "} 
$1=="DTSTART"{DTSTART=$2} 
$1=="CREATED"{CREATED=$2} 
$1=="LAST-MODIFIED"{LASTMODIFIED=$2} 
$1=="SUMMARY"{SUMMARY=$2} 
$1=="LOCATION"{LOCATION=$2} 
$1=="END"{ 
     if (CREATED==LASTMODIFIED) 
       print "\nNew Event Created" 
     else 
       print "\nLast Modified Event" 

     print DTSTART,SUMMARY,LOCATION 
} 

あなたはそれが好きで実行することができます。

コロンとawkスクリプトプロセスによってファイル内のフィールドを分割
awk -F":" -f ics.awk yourfile.ics 

ファイルを1行ずつ表示します。見つかったときに値を取得し、「END」の行が見つかると値を出力します。

上記のスクリプトは、あなたが閉じ取得します:@JNevillとしてではなく、連想配列と同じロジックを使用して

New Event Created 
20160612T201000Z Ash vs Evil Dead Saison 1 Episode 9 & 10 OCS Choc 

Last Modified Event 
20160612T201000Z The Mysteries Of Laura Saison 2 Episode 1 à 4 RTS Un (Suisse) 
+0

ニース。 OPがターゲットプラットフォーム上でbash 4以降を持っていない場合は、これをお勧めします。 –

+0

@JNevill 私はICSファイルで、この結果を得る:ローラセゾンF '新規イベントCreated' ' OCS Chocvilデッドセゾン1つのエピソード9&10 ' '最終更新Event' ' RTSアン(スイス) 2エピソード1à4' 私は何かを見逃しましたか? –

+0

@SaberPendragonこれは、 "DTSTART"と "LOCATION"は、Awkがレコードの最初のフィールドでそれを見つけていないので、変数が設定されていないので、最初のフィールドの正しい値ではないことを示しています。印刷。 – JNevill

1

を:

ics.awk

BEGIN { FS=":" } 
{ a[$1] = $2 } 
$1 == "END" { 
    printf("%s\n%s %s %s\n\n", 
    a["CREATED"] == a["LAST-MODIFIED"] ? "New Event Created" : "Last Modified Event", 
    a["DTSTART"], a["SUMMARY"], a["LOCATION"]) 
} 

をし、次いでそれを呼び出します:

% awk -f ics.awk input-file 
New Event Created 
20160612T201000Z Ash vs Evil Dead Saison 1 Episode 9 & 10 OCS Choc 

Last Modified Event 
20160612T201000Z The Mysteries Of Laura Saison 2 Episode 1 Ã 4 RTS Un (Suisse) 


しかしながら、後続の改行を残します。

+0

この質問では、目的の出力セクション(各フィールドが異なるタイムゾーンを持つ可能性があるため、興味深い問題になる可能性がある)でローカルタイム形式の日付が表示され、実際のICSファイルを解析するには入力時にDOS改行をうまく処理する必要があることに注意してください。 –

関連する問題