所以我找到了这个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
}删除此行/^KEYWORD1/
所以没有删除任何内容/^KEYWORD2/d
,执行!d然后/^KEYWORD2/d
,因为这是使用的最后一个正则表达式所以此时我不确定如何打印之前和之后的行,因为它不执行命令(!d
),除非模式范围标志设置为true。
或者sed至少查看每一行的命令,因为第一个命令是反向删除,它以某种方式更改逻辑以删除模式范围bool为false的所有其他行?
有关此sed表达方式如何运作的任何说明将不胜感激。我上下阅读this great resource但仍然不太了解表达式的所有细节。
答案 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
我们不想打印KEYWORD1
和KEYWORD2
。
对于这些行,我们会转到//d
,这意味着“删除最后一个匹配的行”。
在KEYWORD1
行,我们会删除并删除该行,因为它之前已匹配。在接下来的三行中,我们失败了,但没有匹配,所以我们不删除任何内容。在KEYWORD2
行,我们会删除并删除,因为它之前已匹配 - 让我们留下两种模式之间的界限。