gafm
gafm

Reputation: 351

Split multiple lines after matching a pattern

Sorry for a newbie question but i have a file that looks like this and wanted to capture a line after a certain string which is /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   ....     .

i wanted to take out a certain line after say for example /aggr0 and redirect it to a file. so sample would be, file1 will have this information

/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   ....     .

and then file2 would be this information and so on.

/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   ....     .

so it's like segregating the information on the file.

had this command below but since lines after aggr are not the same, it will only show what was defined (which is 7)

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

but it's only showing what I grepped.

this command here prints 2 lines after matching the pattern however what i want is to redirect it to a file.

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

any idea how can I accomplish it.

Upvotes: 2

Views: 642

Answers (2)

potong
potong

Reputation: 58391

This might work for you (GNU csplit):

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

This will produce 4 file from your example file0 file1 file2 file3, where file0 is empty. If you don't mind numbers starting from zero, use:

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

This will elide the first empty file.


For a sed solution using bash:

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

In essence - this gathers up a split of the file in the hold space and writes it out when it encounters the next split or the at the end of the file.

The file number is prepped when the first split is encountered as the first line of the hold space and after the split is written out, the file number is also incremented using standard bash arithmetic and replaces the contents of the hold space.

Upvotes: 1

anubhava
anubhava

Reputation: 785098

You may use this awk:

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

Upvotes: 2

Related Questions