如何使用Unix grep删除整块不需要的文本?

时间:2013-12-05 05:23:00

标签: unix grep

一直在努力尝试,但仍然无法找到任何更明智的方法......

示例:

### this is the whole block structure ###
text_text_text
text_text_text
text_text_text
apple
### another block ###
text_text_text
text_text_text
text_text_text
orange

执行less <file_name> | grep -B3 "apple" | less将返回:

text_text_text
text_text_text
text_text_text
apple

但现在我的要求是我不想要这个块(用苹果)。我确定我不想要什么,但不确定我想要什么。所以我不能这样做

less <file_name> | grep -B3 "orange" |less

如果我要:

less <file_name> | grep -v "apple" | less

然后只删除与苹果相关的单行,与苹果相关的块将保留在那里。

我试过

less <file_name> | grep -v -B3 "apple" | less

但这似乎不起作用。

那么有什么方法可以帮助我删除与苹果相关的块?

3 个答案:

答案 0 :(得分:2)

删除不需要的块的一种方法是使用tacsed。话说:

tac <filename> | sed '/apple/,+3d' | tac

将返回:

### this is the whole block structure ###
### another block ###
text_text_text
text_text_text
text_text_text
orange

获取样本数据。


说明:tac反转文件中的行。 /apple/,+3将匹配apple和接下来的3行。 ddelete命令。

因为您需要删除模式apple和之前的3行;我们反转文件中的行,找到apple,删除它和接下来的3行,然后再次反转这些行以获得所需的结果。

您可能还想引用sed manual

答案 1 :(得分:0)

使用awk并假设每个块长5个记录。

cat file
### anoter block ###
text_text_text
text_text_text
text_text_text
banan
### this is the whole block structure ###
text_text_text
text_text_text
text_text_text
apple
### another block ###
text_text_text
text_text_text
text_text_text
orange

awk '{a[NR]=$0} /apple/ {f=NR} END {for (i=1;i<=NR;i++) if (i<f-4 || i>f) print a[i]}'
### anoter block ###
text_text_text
text_text_text
text_text_text
banan
### another block ###
text_text_text
text_text_text
text_text_text
orange

答案 2 :(得分:0)

使用awk:

awk '/^apple$/{cs=0;next} 
           { c[cs++]=$0 }
    cs > 3 {
       print c[0];
       for (i=0;i<3;i++){c[i]=c[i+1]}; cs--;
    }
    END    { for (i=0;i<cs;i++){print c[i]} }' input