sed regexp 地址范围减去(或加上)行数

sed regexp 地址范围减去(或加上)行数

我有多个 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

相关内容