使用sed获取两个关键词之间的文本(但不是关键词本身)

时间:2016-02-09 01:29:51

标签: bash sed

所以我找到了这个sed表达式,用于获取关键字之外的关键字:

cat example.txt | sed '/^KEYWORD1/,/^KEYWORD2/!d; //d'

其中example.txt:

do
not
care
KEYWORD1
I
want
this
KEYWORD2
do
not
care

输出:

I
want
this

但是,我想知道这个表达式是怎么回事。我的理解是,使用'模式范围'(如果这是不正确的术语,请纠正我),当你点击第一个匹配时设置bool并且只有当bool为真时才执行模式范围之后的命令

然后有//d,其中//应该表示匹配的最后一个表达式/正则表达式。因此,在具有模式范围的情况下,逻辑如下是正确的:

  • 查找/^KEYWORD1/,将bool设置为true,继续执行!d命令,该命令不会删除此行,然后由于上一个正则表达式为/^KEYWORD1/,因此//d实际上是/^KEYWORD1/d }删除此行
  • bool为true所以它继续不删除3行,并且在所述行上找不到/^KEYWORD1/所以没有删除任何内容
  • 查找/^KEYWORD2/d,执行!d然后/^KEYWORD2/d,因为这是使用的最后一个正则表达式

所以此时我不确定如何打印之前和之后的行,因为它不执行命令(!d),除非模式范围标志设置为true。

或者sed至少查看每一行的命令,因为第一个命令是反向删除,它以某种方式更改逻辑以删除模式范围bool为false的所有其他行?

有关此sed表达方式如何运作的任何说明将不胜感激。我上下阅读this great resource但仍然不太了解表达式的所有细节。

1 个答案:

答案 0 :(得分:1)

您的误解是这样的:/address/!d并不意味着“如果我们匹配address,请不要删除该行”; !是地址的否定,即“如果我们匹配address,那么删除这条线。“

所以单行(顺便说一句,没有cat写得更好)

sed '/^KEYWORD1/,/^KEYWORD2/!d; //d' example.txt

这样做:

  • /^KEYWORD1/,/^KEYWORD2/!d:对于/^KEYWORD1/,/^KEYWORD2/范围之外的所有行,即

    do
    not
    care
    do
    not
    care
    

    删除它们。 d跳回到脚本的开头。这给我们留下了

    KEYWORD1
    I
    want
    this
    KEYWORD2
    

    我们不想打印KEYWORD1KEYWORD2

  • 对于这些行,我们会转到//d,这意味着“删除最后一个匹配的行”。

    KEYWORD1行,我们会删除并删除该行,因为它之前已匹配。在接下来的三行中,我们失败了,但没有匹配,所以我们不删除任何内容。在KEYWORD2行,我们会删除并删除,因为它之前已匹配 - 让我们留下两种模式之间的界限。