关于bash:使用awk/sed/grep从文件中的匹配模式中删除上下多行

 2022-02-12 

Delete multiple lines above and below from a matching pattern in a file using awk/sed/grep

我有 file.txt 包含:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
registered
{
    hostname-1
    {
        AAA 32;
        BBB uuid-1;
        ip 192.168.1.1;
        host hostname-1;
        ...
        ...
        ...
    }
}
registered
{
    hostname-2
    {
        AAA 31;
        BBB uuid-2;
        ip 192.168.1.2;
        host hostname-2;
        ...
        ...
        ...
    }
}
registered
{
    hostname-3
    {
        AAA 33;
        BBB uuid-3;
        ip 192.168.1.3;
        host hostname-3;
        ...
        ...
        ...
    }
}

我想根据匹配的ip删除一个完整的注册块。

例如如果 ip 是 192.168.1.2 那么输出应该是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
registered
{
    hostname-1
    {
        AAA 32;
        BBB uuid-1;
        ip 192.168.1.1;
        host hostname-1;
        ...
        ...
        ...
    }
}
registered
{
    hostname-3
    {
        AAA 33;
        BBB uuid-3;
        ip 192.168.1.3;
        host hostname-3;
        ...
        ...
        ...
    }
}

我尝试了 2 种方法来实现这一点,但无法成功

1) 使用 grep:这不起作用。

1
2
grep -v -B6 -A6 $IP file.txt > out.txt
mv -f out.txt file.txt

2) 使用 awk:
如果我在下面的 awk 命令中给出确切的 IP,那么它可以工作

1
awk '/192.168.1.2/{for(x=NR-6;x<=NR+6;x++)d[x];}{a[NR]=$0}END{for(i=1;i<=NR;i++)if(!(i in d))print a[i]}' file.txt

但我想在 awk 命令中传递变量 $IP。它不工作

1
awk -v pattern="${IP}" '$0 ~ pattern/{for(x=NR-6;x<=NR+6;x++)d[x];}{a[NR]=$0}END{for(i=1;i<=NR;i++)if(!(i in d))print a[i]}' file.txt

任何帮助找出这里的问题将不胜感激。

谢谢。


这可能对你有用(GNU sed):

1
sed -n '/^registered/h;//!H;/^}/!b;g;/192\\.168\\.1\\.2/!p' file

提供文件原样。这将收集整个注册块并删除包含字符串 192.168.1.2.

的块


1
2
IP=192.168.1.2
awk '/'$IP'/{for(x=NR-6;x<=NR+6;x++)d[x];}{a[NR]=$0}END{for(i=1;i<=NR;i++)if(!(i in d))print a[i]}' file.txt