匹配模式后拆分多行

Split multiple lines after matching a pattern

抱歉新手问题,但我有一个看起来像这样的文件,想在某个字符串 /aggr 之后捕获一行。

/aggr0_usts_nz_3001/plex0/rg0:
9g.10.0            0   4.08    0.00   ....     .   4.08   1.00    41   0.00   ....     .
1a.10.1            0   4.08    0.00   ....     .   4.08   1.00    10   0.00   ....     .
9g.10.4            0   4.08    0.00   ....     .   4.08   1.00    49   0.00   ....     .
1a.10.1            0   0.00    0.00   ....     .   0.00   ....     .   0.00   ....     .
9g.10.4            0   0.00    0.00   ....     .   0.00   ....     .   0.00   ....     .
/aggr1_usts_nz_3001/plex0/rg0:
1e.00.0            0   0.00    0.00   ....     .   0.00   ....     .   0.00   ....     .
9o.01.44           0   0.00    0.00   ....     .   0.00   ....     .   0.00   ....     .
1e.00.1            4 994.04  994.04   1.44   119   0.00   ....     .   0.00   ....     .
9o.01.41           4 981.91  981.91   1.41   141   0.00   ....     .   0.00   ....     .
1e.00.4            4 811.19  811.19   1.14   149   0.00   ....     .   0.00   ....     .
9o.01.14           4 809.99  809.99   1.14   119   0.00   ....     .   0.00   ....     .
1e.00.1            4 980.86  980.86   1.19   144   0.00   ....     .   0.00   ....     .
9o.01.11           4 998.89  998.89   1.11   140   0.00   ....     .   0.00   ....     .
/aggr1_usts_nz_3001/plex0/rg1:
9a.10.14           0   0.00    0.00   ....     .   0.00   ....     .   0.00   ....     .
9e.40.14           0   0.00    0.00   ....     .   0.00   ....     .   0.00   ....     .
1g.11.14           4 999.10  999.10   1.16   110   0.00   ....     .   0.00   ....     .
1o.41.14           4 996.90  996.90   1.44   118   0.00   ....     .   0.00   ....     .
9a.10.11           4 911.11  911.11   1.44   116   0.00   ....     .   0.00   ....     .
9e.40.11           4 919.48  919.48   1.11   141   0.00   ....     .   0.00   ....     .
1g.11.11           4 900.44  900.44   1.16   146   0.00   ....     .   0.00   ....     .
1o.41.11           1 694.19  694.19   1.19   109   0.00   ....     .   0.00   ....     .
9a.10.14           4 941.44  941.44   1.61   111   0.00   ....     .   0.00   ....     .

我想在例如 /aggr0 之后取出某一行并将其重定向到一个文件。所以示例将是,文件 1 将包含此信息

/aggr0_usts_nz_3001/plex0/rg0:
9g.10.0            0   4.08    0.00   ....     .   4.08   1.00    41   0.00   ....     .
1a.10.1            0   4.08    0.00   ....     .   4.08   1.00    10   0.00   ....     .
9g.10.4            0   4.08    0.00   ....     .   4.08   1.00    49   0.00   ....     .
1a.10.1            0   0.00    0.00   ....     .   0.00   ....     .   0.00   ....     .
9g.10.4            0   0.00    0.00   ....     .   0.00   ....     .   0.00   ....     .

然后file2就是这个信息等等。

/aggr1_usts_nz_3001/plex0/rg0:
1e.00.0            0   0.00    0.00   ....     .   0.00   ....     .   0.00   ....     .
9o.01.44           0   0.00    0.00   ....     .   0.00   ....     .   0.00   ....     .
1e.00.1            4 994.04  994.04   1.44   119   0.00   ....     .   0.00   ....     .
9o.01.41           4 981.91  981.91   1.41   141   0.00   ....     .   0.00   ....     .
1e.00.4            4 811.19  811.19   1.14   149   0.00   ....     .   0.00   ....     .
9o.01.14           4 809.99  809.99   1.14   119   0.00   ....     .   0.00   ....     .
1e.00.1            4 980.86  980.86   1.19   144   0.00   ....     .   0.00   ....     .
9o.01.11           4 998.89  998.89   1.11   140   0.00   ....     .   0.00   ....     .

所以这就像隔离文件上的信息。

下面有这个命令,但由于 aggr 之后的行不相同,它只会显示定义的内容(即 7)

for i in `cat sample.txt`; do
    echo $i | grep aggr* -A 7
done

但它只显示了我 grep 的内容。

此命令在匹配模式后打印 2 行,但我想要的是将其重定向到文件。

awk '/aggr/{x=NR+2}(NR<=x){print}' sample.txt

知道我该如何完成它。

你可以使用这个awk:

awk '/^\/aggr/ {close(fn); fn = "file" ++fNo ".txt"} {print > fn}' file

这可能适合您 (GNU csplit):

csplit -n1 -ffile file '/^\/aggr/' '{*}'

这将从您的示例 file0 file1 file2 file3 生成 4 个文件,其中 file0 为空。如果您不介意数字从零开始,请使用:

csplit -zn1 -ffile file '/^\/aggr/' '{*}'

这将删除第一个空文件。


对于使用 bash 的 sed 解决方案:

sed -En '/^\/aggr/!b;x;s/^/1/;x;:a;H;$!{n;/^\/aggr/!ba};x
        s/^(\S+)\n(.*)/echo "" > file;echo $((+1))/e;x;$!ba' file

本质上 - 这会收集保留 space 中的文件拆分,并在遇到下一个拆分或文件末尾时将其写出。

文件编号在遇到第一个拆分作为保留的第一行时准备 space 并且在拆分写出后,文件编号也使用标准 bash 算法递增并替换保留 space.

的内容