AWK:生成icalendar文件。如何打印一些连续的行?

时间:2019-05-31 11:11:00

标签: awk icalendar

  

多亏了Ed Morton的回答,我可以使用Thunderbird和icalendar验证程序进行一些测试。我编辑了我的问题,添加了没有说明的条目以及具有精确要求的预期结果。

我正在编写一个脚本,以从平面文本文件生成icalendar文件。我想获取描述内容以及日期之后的行。说我有一个计划文件:

lun 06 05 2019 08 15 09 00 F206
    A descritpion text.
ven 10 05 2019 11 00 11 45 G202
    Another description text
    - on multiple; 
    - lines.
lun 13 05 2019 08 15 09 00 F206
ven 17 05 2019 11 00 11 45 G202
    A long description with more than 75 characters.
    This happen often when multiple lines are
    joined in one. So the program shoud split every lines
    To 75 characters including the word description.
lun 20 05 2019 08 15 09 00 F206
    A description text.

我的脚本看起来像这样,我是awk的新手:

#!/bin/bash
awk ' BEGIN { print "BEGIN:VCALENDAR\r\n\
... some entries here ...\r\n\
END:VTIMEZONE\r" ;}
$1~/^(lun|mar|mer|jeu|ven)$/ { print "BEGIN:VEVENT\r\n\
... some entries here ...\r\n\
DTSTART;TZID=Europe/Zurich:"$4""$3""$2"T"$5""$6"00\r\n\
DTEND;TZID=Europe/Zurich:"$4""$3""$2"T"$7""$8"00\r\n\
TRANSP:OPAQUE\r\n\
DESCRIPTION: >>>HERE I NEED THE DESCRIPTIVE LINES<<<< \r\n\
END:VEVENT\r"}
END { print "END:VCALENDAR" } ' < $1 > $1.ics

预期结果:

BEGIN:VCALENDAR
BEGIN:VEVENT
DTSTART;TZID=Europe/Zurich:20190506T081500
DTEND;TZID=Europe/Zurich:20190506T090000
DESCRIPTION:A descritpion text.
END:VEVENT
BEGIN:VEVENT
DTSTART;TZID=Europe/Zurich:20190510T110000
DTEND;TZID=Europe/Zurich:20190510T114500
DESCRIPTION:Another description text\n- on multiple;\n- lines.
END:VEVENT
BEGIN:VEVENT
DTSTART;TZID=Europe/Zurich:20190513T081500
DTEND;TZID=Europe/Zurich:20190513T090000
END:VEVENT                  
BEGIN:VEVENT
DTSTART;TZID=Europe/Zurich:20190517T110000
DTEND;TZID=Europe/Zurich:20190517T114500
DESCRIPTION:A long description with more than 75 characters.\nThis happen
 often when multiple lines are\njoined in one. So the program shoud split 
 every lines\nTo 75 characters including the word description.
END:VEVENT
BEGIN:VEVENT
DTSTART;TZID=Europe/Zurich:20190520T081500
DTEND;TZID=Europe/Zurich:20190520T090000
DESCRIPTION: A description text.
END:VEVENT
END:VCALENDAR

因此确切的要求是:

  1. 没有描述的行不应打印DESCRIPTION:。
  2. 多行描述应以文字\ n分隔。这与printf "%s%s", $0, "\\n"
  3. 一起使用
  4. 应将行拆分为少于75个字符,以\ r \ n
  5. 结尾
  6. 其他描述行应以空格开头。

2 个答案:

答案 0 :(得分:1)

您确实在正确的轨道上。这是与flag逻辑集成的脚本:

#!/bin/bash
awk 'BEGIN {print "BEGIN:VCALENDAR\r\n\
... some entries here ...\r\n\
END:VTIMEZONE\r" ;}
$1~/^(lun|mar|mer|jeu|ven)$/ && flag {flag = !flag; print "END:VEVENT\r"}
$1~/^(lun|mar|mer|jeu|ven)$/ && !flag {flag = !flag; print "BEGIN:VEVENT\r\n\
... some entries here ...\r\n\
DTSTART;TZID=Europe/Zurich:"$4""$3""$2"T"$5""$6"00\r\n\
DTEND;TZID=Europe/Zurich:"$4""$3""$2"T"$7""$8"00\r\n\
TRANSP:OPAQUE\r\n\
DESCRIPTION: "; next}
flag {print $0}
END { print "END:VCALENDAR" } ' < $1

输出:

BEGIN:VCALENDAR
... some entries here ...
END:VTIMEZONE
BEGIN:VEVENT
... some entries here ...
DTSTART;TZID=Europe/Zurich:20190506T081500
DTEND;TZID=Europe/Zurich:20190506T090000
TRANSP:OPAQUE
DESCRIPTION:
    Some descriptive lines here.
    Lorem ipsumi dolor sit amet, consectetur adipiscing elitr.
END:VEVENT
BEGIN:VEVENT
... some entries here ...
DTSTART;TZID=Europe/Zurich:20190510T110000
DTEND;TZID=Europe/Zurich:20190510T114500
TRANSP:OPAQUE
DESCRIPTION:
    sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut
    - enim
    - ad minim veniam.
END:VEVENT
BEGIN:VEVENT
... some entries here ...
DTSTART;TZID=Europe/Zurich:20190513T081500
DTEND;TZID=Europe/Zurich:20190513T090000
TRANSP:OPAQUE
DESCRIPTION:
    exercitation ullamco
END:VEVENT
BEGIN:VEVENT
... some entries here ...
DTSTART;TZID=Europe/Zurich:20190517T110000
DTEND;TZID=Europe/Zurich:20190517T114500
TRANSP:OPAQUE
DESCRIPTION:
    quis nostrud
END:VCALENDAR

答案 1 :(得分:1)

$ cat tst.awk
BEGIN {
    ORS="\r\n"

    print "BEGIN:VCALENDAR"
    print "... some entries here ..."
    print "END:VTIMEZONE"
}
/^[^[:space:]]/ {
    prtEndVevent()

    print "BEGIN:VEVENT"
    print "... some entries here ..."

    date = $4 $3 $2
    begt = $5 $6 "00"
    endt = $7 $8 "00"

    print "DTSTART;TZID=Europe/Zurich:" date "T" begt
    print "DTEND;TZID=Europe/Zurich:"   date "T" endt
    next
}
{
    gsub(/^[[:space:]]+|[[:space:]]+$/,"")
    desc = (desc == "" ? "DESCRIPTION:" : desc RS) $0
}
END {
    prtEndVevent()
    print "END:VCALENDAR"
}

function prtEndVevent(       wid) {
    if ( desc != "" ) {
        wid = 74
        gsub(RS,"\\n",desc)
        while ( desc !~ /^ ?$/ ) {
            print substr(desc,1,wid)
            desc = " " substr(desc,wid+1)
        }
        desc = ""
    }
    if ( endVevent != "" ) {
        print endVevent
    }
    endVevent = "END:VEVENT"
}

$ awk -f tst.awk file
BEGIN:VCALENDAR
... some entries here ...
END:VTIMEZONE
BEGIN:VEVENT
... some entries here ...
DTSTART;TZID=Europe/Zurich:20190506T081500
DTEND;TZID=Europe/Zurich:20190506T090000
DESCRIPTION:A descritpion text.
END:VEVENT
BEGIN:VEVENT
... some entries here ...
DTSTART;TZID=Europe/Zurich:20190510T110000
DTEND;TZID=Europe/Zurich:20190510T114500
DESCRIPTION:Another description text\n- on multiple;\n- lines.
END:VEVENT
BEGIN:VEVENT
... some entries here ...
DTSTART;TZID=Europe/Zurich:20190513T081500
DTEND;TZID=Europe/Zurich:20190513T090000
END:VEVENT
BEGIN:VEVENT
... some entries here ...
DTSTART;TZID=Europe/Zurich:20190517T110000
DTEND;TZID=Europe/Zurich:20190517T114500
DESCRIPTION:A long description with more than 75 characters.\nThis happen
 often when multiple lines are\njoined in one. So the program shoud split
 every lines\nTo 75 characters including the word description.
END:VEVENT
BEGIN:VEVENT
... some entries here ...
DTSTART;TZID=Europe/Zurich:20190520T081500
DTEND;TZID=Europe/Zurich:20190520T090000
DESCRIPTION:A description text.
END:VEVENT
END:VCALENDAR

请注意,这是在字符位置而不是单词边界处换行,因此,如果单词越过第75个字符位置,则会被拆分。如果不希望这样,您可以更新prtDesc()一次打印一个单词,检查所有单词+打印的空白加下一个单词的总长度是否小于75(并决定如何处理描述字符串是75个以上的字符,没有空格!),或调用UNIX命令fold为您包装。

如果您正考虑使用getline,请务必先阅读并完全理解http://awk.freeshell.org/AllAboutGetline