我有多个 ICS 文件,其中包含以下内容:
...
PRIORITY:4
DESCRIPTION:this
was
a
triumph
COMPLETED:20180101T160000
...
我有兴趣解决DESCRIPTION
关键问题。该密钥DESCRIPTION
可以出现在 ICS 文件中的任何位置。这是不是总是跟着钥匙COMPLETED
。
使用ed
,我会这样做:
/DESCRIPTION/;/^[^ ]/-1p
结果是:
DESCRIPTION:this
was
a
triumph
然而,sed
似乎没有这个能力:
sed -n '/DESCRIPTION/,/^[^ ]/-1p' filename
结果是
sed:-e 表达式 #1,字符 22:未知命令:`-'
有没有办法做我想做的事sed
?
解决这个特殊问题
这个问题可以通过以下方法解决:
sed -n '/DESCRIPTION:/,/^\S/ { /\(DESCRIPTION\|^\s\)/p }' example.ics
但这感觉非常笨拙和冗长。
awk
似乎也不支持/begpat/,/endpat/-1
,所以你最终会得到类似的结果:
BEGIN { endpat = "^(DESCRIPTION|\\s)" }
/^DESCRIPTION/, $0 !~ endpat {
if ($0 ~ endpat) {print}
}
答案1
你已经很接近了:
sed '/DESCRIPTION/p;//,/^[^ ]/!d;//d' filename
会做你想做的事。为什么?
- 您可以定义一个范围并删除该范围之外的所有内容
/start/,/stop/!d
- 然后您还想删除匹配的最后一行。以下
//d
将这样做(空模式//
与最后一个模式匹配,因此该/stop/
行) - 但在你的情况下,该模式也与第一行匹配。厄运!所以让我们
p
先打印它,然后你会得到我显示的命令(再次使用空模式)
使用不同的方法进行更新
在您的评论中,您将其称为“解决方法”,这是从某些角度来看的。事实上,对于我自己来说,我会选择一种不同的、更sed
接近的方法:
sed '/^ /{H;d;};x;/^DESCRIPTION/!d' filename
这对于情侣来说应该感觉很自然sed
,但对于某些人来说乍一看可能很奇怪。它遵循“希望我能记得“-方法。那是什么?每次你遇到没有缩进的行时,你都会想“我希望我能记住之前的行,它们是否值得打印”。然后我们简单地假设我们已经记住了它们,保留空间,因此我们可以简单地x
更改模式空间和保留空间,d
如果它不是以以下方式开头,则将其删除DESCRIPTION
(如果以以下方式开头,则默认情况下将打印它)。
好处是x
,每条未缩进的行都会自动位于保留空间中,因此我们只需要将缩进的行添加到保留空间中即可H
。这就是该/^ /{H;d;}
部分的作用(d
是为了避免输出或对这些行进行进一步处理)。
现在,程序员会做相反的事情。他们可能会做这样的循环:
sed '/DESCRIPTION/!d
:loop
N;/\n[^ ].*/!bloop
s///' filename
也就是说,删除所有内容,直到遇到DESCRIPTION
关键字,然后启动一个循环来收集带有 的行,N
并循环直到出现带有非空格的行\n[^ ].*
。在这种情况下,删除最后一行(再次利用空模式)。
这也有效,但这不是sed
.
答案2
是的,sed 支持这样的地址范围:
sed -n '/string1/,/string2/p file
在您的情况下,尝试使用-E
扩展正则表达式的选项。
sed -nE '/this/,/^[^ ]/p' filename