SED如何删除两个模式之间的特定行?

4

我正在尝试使用sed过滤一个*.ics文件。这个*.ics文件看起来像这样:

[...]

BEGIN:VEVENT
UID:0xfoo
SUMMARY:foo
DTSTART:20131212T090000
DTEND:20131212T100000
SEQUENCE:0
DTSTAMP:20131212T100000
LOCATION:foo
CATEGORIES:foo
DESCRIPTION:foo
CLASS:PUBLIC
END:VEVENT

[...]

我希望删除以UIDSEQUENCE开头的行,但只有当它们在BEGIN:VEVENTEND:VEVENT之间时才删除。
我尝试使用以下方法删除这些行:
sed '/^BEGIN:VEVENT/,/^END:VEVENT/ /^UID/d'

但它只会返回一个错误,类似于未知命令'/'

如何删除这些行呢?

谢谢!

3个回答

9

试试这行代码:

 sed '/^BEGIN:VEVENT/,/^END:VEVENT/{/^\(UID\|SEQUENCE\)/d}' file

5

sed是一个用于在单行上进行简单替换的优秀工具,对于其他任何事情,只需使用awk:

awk '
/BEGIN:VEVENT/ { inBlock = 1 }
inBlock {
    if ( /END:VEVENT/ ) {
        inBlock = 0
    }
    else if ( /^(UID|SEQUENCE)/ ) {
        next
    }
}
{ print }
' file

伪代码说明(inBlock 是一个布尔变量,line 只是一个想象的字符串变量):
WHILE read line from file DO

    IF ( line contains the regexp "BEGIN:VEVENT" ) THEN
        inBlock = TRUE

    ENDIF

    IF ( inBlock == TRUE ) THEN

        IF ( line contains the regexp "END:VEVENT" ) THEN
            inBlock = FALSE

        ELSIF ( line starts with the regexp "UID" or "SEQUENCE" ) THEN
            do no further processing on this line

        ENDIF

    ENDIF

    print the current line

ENDWHILE

1
谢谢您的建议!我以前并没有经常使用 awk,所以我不太明白它在这里到底是做什么的。等我有时间了,我会去研究一下! - edloaa
1
我添加了伪代码解释,以便帮助理解。请记住,awk使用内置的while-not-eof循环读取行,并且awk脚本中的每个语句都由<condition> { <action> }段组成(其中如果条件为真,则执行操作),这样你就可以理解了。 - Ed Morton

1
另一个 awk
awk '/^BEGIN:VEVENT/,/^END:VEVENT/ {if ($0~/^UID|^SEQUENCE/) next}1' file

如果在从 BEGIN:VEVENTEND:VEVENT 的块部分中,行以 UIDSEQUENCE 开头,则跳过该行。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接