匹配模式后拆分多行
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.
的内容
抱歉新手问题,但我有一个看起来像这样的文件,想在某个字符串 /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.
的内容