With GNU awk, you can set the record separator to a regular expression:
<file awk 'NR==n+1 { print rt, $0 } { rt = RT }' RS='\\<category' ORS='' n=3
Output:
category 3 r d done
RT is a record separator delimiter. Note that a record with respect to n will be disabled by one, since the first record refers to what precedes the first RS .
Edit
According to Ed's comment, this will not work if the records have other data between them, for example:
category 1 s t done category 2 n d done foo category 3 r d done bar category 4 t h done
One way around this is to clear the input with the second (or first) awk:
<file awk '/^category$/,/^done$/' | awk 'NR==n+1 { print rt, $0 } { rt = RT }' RS='\\<category' ORS='' n=3
Output:
category 3 r d done
Edit 2
As Ed noted in the comments, the above methods are not looking for the final template. One way to do this that other answers have not been addressed to is getline (note that there are some caveats with awk GetLine):
<file awk ' /^category$/ { v = $0 while(!/^done$/) { if(!getline) exit v = v ORS $0 } if(++nr == n) print v }' n=3
In one line:
<file awk '/^category$/ { v = $0; while(!/^done$/) { if(!getline) exit; v = v ORS $0 } if(++nr == n) print v }' n=3
Thor
source share